Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3253bf40 authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Updating sticky headers." into ub-launcher3-burnaby

parents 5b370735 de34aa40
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@
                android:paddingBottom="12dp"
                android:contentDescription="@string/all_apps_button_label"
                android:src="@drawable/ic_arrow_back_grey" />
            <EditText
            <com.android.launcher3.AppsContainerSearchEditTextView
                android:id="@+id/app_search_box"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
@@ -59,6 +59,7 @@
                android:textColor="#4c4c4c"
                android:textColorHint="#9c9c9c"
                android:imeOptions="actionDone|flagNoExtractUi"
                android:focusableInTouchMode="true"
                android:background="@android:color/transparent" />
        </LinearLayout>
        <ImageView
+32 −11
Original line number Diff line number Diff line
@@ -104,28 +104,38 @@ public class AlphabeticalAppsList {
        public int position;
        // Whether or not the item at this adapter position is a section or not
        public boolean isSectionHeader;
        // The name of this section, or the section that this app is contained in
        // The name of this section, or the section section name of the app.  Note that if this
        // app was merged into another section, then this may be a different name than the
        // sectionInfo's sectionName
        public String sectionName;
        // The section to which this app belongs
        public SectionInfo sectionInfo;
        // The index of this app in the section
        public int sectionAppIndex;
        // The associated AppInfo, or null if this adapter item is a section
        public AppInfo appInfo;
        // The index of this app (not including sections), or -1 if this adapter item is a section
        public int appIndex;

        public static AdapterItem asSection(int pos, String name) {
        public static AdapterItem asSection(int pos, SectionInfo section) {
            AdapterItem item = new AdapterItem();
            item.position = pos;
            item.isSectionHeader = true;
            item.sectionName = name;
            item.sectionInfo = section;
            item.sectionName = section.sectionName;
            item.appInfo = null;
            item.appIndex = -1;
            return item;
        }

        public static AdapterItem asApp(int pos, String sectionName, AppInfo appInfo, int appIndex) {
        public static AdapterItem asApp(int pos, SectionInfo section, String sectionName,
                                        int sectionAppIndex, AppInfo appInfo, int appIndex) {
            AdapterItem item = new AdapterItem();
            item.position = pos;
            item.isSectionHeader = false;
            item.sectionInfo = section;
            item.sectionName = sectionName;
            item.sectionAppIndex = sectionAppIndex;
            item.appInfo = appInfo;
            item.appIndex = appIndex;
            return item;
@@ -140,7 +150,7 @@ public class AlphabeticalAppsList {
    }

    // The maximum number of rows allowed in a merged section before we stop merging
    private static final int MAX_ROWS_IN_MERGED_SECTION = Integer.MAX_VALUE;
    private static final int MAX_ROWS_IN_MERGED_SECTION = 3;

    private List<AppInfo> mApps = new ArrayList<>();
    private List<AppInfo> mFilteredApps = new ArrayList<>();
@@ -314,6 +324,7 @@ public class AlphabeticalAppsList {
        SectionInfo lastSectionInfo = null;
        int position = 0;
        int appIndex = 0;
        int sectionAppIndex = 0;
        for (AppInfo info : mApps) {
            String sectionName = mIndexer.computeSectionName(info.title.toString().trim());

@@ -325,11 +336,12 @@ public class AlphabeticalAppsList {
            // Create a new section if necessary
            if (lastSectionInfo == null || !lastSectionInfo.sectionName.equals(sectionName)) {
                lastSectionInfo = new SectionInfo(sectionName);
                sectionAppIndex = 0;
                mSections.add(lastSectionInfo);

                // Create a new section item, this item is used to break the flow of items in the
                // list
                AdapterItem sectionItem = AdapterItem.asSection(position++, sectionName);
                AdapterItem sectionItem = AdapterItem.asSection(position++, lastSectionInfo);
                if (!AppsContainerView.GRID_HIDE_SECTION_HEADERS && !hasFilter()) {
                    lastSectionInfo.sectionItem = sectionItem;
                    mSectionedFilteredApps.add(sectionItem);
@@ -337,7 +349,8 @@ public class AlphabeticalAppsList {
            }

            // Create an app item
            AdapterItem appItem = AdapterItem.asApp(position++, sectionName, info, appIndex++);
            AdapterItem appItem = AdapterItem.asApp(position++, lastSectionInfo, sectionName,
                    sectionAppIndex++, info, appIndex++);
            lastSectionInfo.numAppsInSection++;
            if (lastSectionInfo.firstAppItem == null) {
                lastSectionInfo.firstAppItem = appItem;
@@ -361,25 +374,33 @@ public class AlphabeticalAppsList {
                // some limit, and also if there are no lessons to merge.
                while (0 < (sectionAppCount % mNumAppsPerRow) &&
                        (sectionAppCount % mNumAppsPerRow) < minNumAppsPerRow &&
                        (int) Math.ceil(sectionAppCount / mNumAppsPerRow) < MAX_ROWS_IN_MERGED_SECTION &&
                        (sectionAppCount / mNumAppsPerRow) < MAX_ROWS_IN_MERGED_SECTION &&
                        (i + 1) < mSections.size()) {
                    SectionInfo nextSection = mSections.remove(i + 1);

                    // Merge the section names
                    if (AppsContainerView.GRID_MERGE_SECTION_HEADERS) {
                        mergedSectionName += nextSection.sectionName;
                    }
                    // Remove the next section break
                    mSectionedFilteredApps.remove(nextSection.sectionItem);
                    int pos = mSectionedFilteredApps.indexOf(section.firstAppItem);
                    if (AppsContainerView.GRID_MERGE_SECTION_HEADERS) {
                        // Update the section names for the two sections
                        int pos = mSectionedFilteredApps.indexOf(section.firstAppItem);
                        for (int j = pos; j < (pos + section.numAppsInSection + nextSection.numAppsInSection); j++) {
                            AdapterItem item = mSectionedFilteredApps.get(j);
                            item.sectionName = mergedSectionName;
                            item.sectionInfo = section;
                        }
                    }
                    // Update the following adapter items of the removed section
                    int pos = mSectionedFilteredApps.indexOf(nextSection.firstAppItem);
                    // Point the section for these new apps to the merged section
                    for (int j = pos + section.numAppsInSection; j < (pos + section.numAppsInSection + nextSection.numAppsInSection); j++) {
                        AdapterItem item = mSectionedFilteredApps.get(j);
                        item.sectionInfo = section;
                        item.sectionAppIndex += section.numAppsInSection;
                    }
                    // Update the following adapter items of the removed section item
                    pos = mSectionedFilteredApps.indexOf(nextSection.firstAppItem);
                    for (int j = pos; j < mSectionedFilteredApps.size(); j++) {
                        AdapterItem item = mSectionedFilteredApps.get(j);
                        item.position--;
+65 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.launcher3;

import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.EditText;


/**
 * The edit text for the search container
 */
public class AppsContainerSearchEditTextView extends EditText {

    /**
     * Implemented by listeners of the back key.
     */
    public interface OnBackKeyListener {
        public void onBackKey();
    }

    private OnBackKeyListener mBackKeyListener;

    public AppsContainerSearchEditTextView(Context context) {
        this(context, null);
    }

    public AppsContainerSearchEditTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AppsContainerSearchEditTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void setOnBackKeyListener(OnBackKeyListener listener) {
        mBackKeyListener = listener;
    }

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        // If this is a back key, propagate the key back to the listener
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
            if (mBackKeyListener != null) {
                mBackKeyListener.onBackKey();
            }
            return false;
        }
        return super.onKeyPreIme(keyCode, event);
    }
}
+48 −11
Original line number Diff line number Diff line
@@ -51,9 +51,11 @@ public class AppsContainerView extends BaseContainerView implements DragSource,

    private static final boolean ALLOW_SINGLE_APP_LAUNCH = true;
    private static final boolean DYNAMIC_HEADER_ELEVATION = false;
    private static final boolean DISMISS_SEARCH_ON_BACK = true;
    private static final float HEADER_ELEVATION_DP = 4;
    private static final int FADE_IN_DURATION = 175;
    private static final int FADE_OUT_DURATION = 125;
    private static final int FADE_OUT_DURATION = 100;
    private static final int SEARCH_TRANSLATION_X_DP = 18;

    @Thunk Launcher mLauncher;
    @Thunk AlphabeticalAppsList mApps;
@@ -67,7 +69,7 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
    private View mSearchBarContainerView;
    private View mSearchButtonView;
    private View mDismissSearchButtonView;
    private EditText mSearchBarEditView;
    private AppsContainerSearchEditTextView mSearchBarEditView;

    private int mNumAppsPerRow;
    private Point mLastTouchDownPos = new Point(-1, -1);
@@ -192,10 +194,19 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
        mSearchBarContainerView = findViewById(R.id.app_search_container);
        mDismissSearchButtonView = mSearchBarContainerView.findViewById(R.id.dismiss_search_button);
        mDismissSearchButtonView.setOnClickListener(this);
        mSearchBarEditView = (EditText) findViewById(R.id.app_search_box);
        mSearchBarEditView = (AppsContainerSearchEditTextView) findViewById(R.id.app_search_box);
        if (mSearchBarEditView != null) {
            mSearchBarEditView.addTextChangedListener(this);
            mSearchBarEditView.setOnEditorActionListener(this);
            if (DISMISS_SEARCH_ON_BACK) {
                mSearchBarEditView.setOnBackKeyListener(
                        new AppsContainerSearchEditTextView.OnBackKeyListener() {
                            @Override
                            public void onBackKey() {
                                hideSearchField(true, true);
                            }
                        });
            }
        }
        mAppsRecyclerView = (AppsContainerRecyclerView) findViewById(R.id.apps_list_view);
        mAppsRecyclerView.setApps(mApps);
@@ -563,9 +574,16 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
     */
    private void showSearchField() {
        // Show the search bar and focus the search
        final int translationX = DynamicGrid.pxFromDp(SEARCH_TRANSLATION_X_DP,
                getContext().getResources().getDisplayMetrics());
        mSearchBarContainerView.setVisibility(View.VISIBLE);
        mSearchBarContainerView.setAlpha(0f);
        mSearchBarContainerView.animate().alpha(1f).setDuration(FADE_IN_DURATION).withLayer()
        mSearchBarContainerView.setTranslationX(translationX);
        mSearchBarContainerView.animate()
                .alpha(1f)
                .translationX(0)
                .setDuration(FADE_IN_DURATION)
                .withLayer()
                .withEndAction(new Runnable() {
                    @Override
                    public void run() {
@@ -574,38 +592,57 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
                                InputMethodManager.SHOW_IMPLICIT);
                    }
                });
        mSearchButtonView.animate().alpha(0f).setDuration(FADE_OUT_DURATION).withLayer();
        mSearchButtonView.animate()
                .alpha(0f)
                .translationX(-translationX)
                .setDuration(FADE_OUT_DURATION)
                .withLayer();
    }

    /**
     * Hides the search field.
     */
    private void hideSearchField(boolean animated, final boolean returnFocusToRecyclerView) {
        final boolean resetTextField = mSearchBarEditView.getText().toString().length() > 0;
        final int translationX = DynamicGrid.pxFromDp(SEARCH_TRANSLATION_X_DP,
                getContext().getResources().getDisplayMetrics());
        if (animated) {
            // Hide the search bar and focus the recycler view
            mSearchBarContainerView.animate().alpha(0f).setDuration(FADE_IN_DURATION).withLayer()
            mSearchBarContainerView.animate()
                    .alpha(0f)
                    .translationX(0)
                    .setDuration(FADE_IN_DURATION)
                    .withLayer()
                    .withEndAction(new Runnable() {
                        @Override
                        public void run() {
                            mSearchBarContainerView.setVisibility(View.INVISIBLE);
                            if (resetTextField) {
                                mSearchBarEditView.setText("");
                            }
                            mApps.setFilter(null);
                            if (returnFocusToRecyclerView) {
                                mAppsRecyclerView.requestFocus();
                            }
                            scrollToTop();
                        }
                    });
            mSearchButtonView.animate().alpha(1f).setDuration(FADE_OUT_DURATION).withLayer();
            mSearchButtonView.setTranslationX(-translationX);
            mSearchButtonView.animate()
                    .alpha(1f)
                    .translationX(0)
                    .setDuration(FADE_OUT_DURATION)
                    .withLayer();
        } else {
            mSearchBarContainerView.setVisibility(View.INVISIBLE);
            if (resetTextField) {
                mSearchBarEditView.setText("");
            }
            mApps.setFilter(null);
            mSearchButtonView.setAlpha(1f);
            mSearchButtonView.setTranslationX(0f);
            if (returnFocusToRecyclerView) {
                mAppsRecyclerView.requestFocus();
            }
            scrollToTop();
        }
        getInputMethodManager().hideSoftInputFromWindow(getWindowToken(), 0);
    }
+99 −62

File changed.

Preview size limit exceeded, changes collapsed.