193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung/*
293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * Copyright (C) 2015 The Android Open Source Project
393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung *
493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * Licensed under the Apache License, Version 2.0 (the "License");
593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * you may not use this file except in compliance with the License.
693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * You may obtain a copy of the License at
793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung *
893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung *      http://www.apache.org/licenses/LICENSE-2.0
993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung *
1093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * Unless required by applicable law or agreed to in writing, software
1193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * distributed under the License is distributed on an "AS IS" BASIS,
1293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * See the License for the specific language governing permissions and
1493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * limitations under the License.
1593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */
165f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chungpackage com.android.launcher3.allapps;
1793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
1893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.content.Context;
19fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport android.content.res.Resources;
20243fdd7cdf262b341b4f66177af27eec4f5cde45Winson Chungimport android.graphics.Canvas;
21fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport android.graphics.drawable.Drawable;
2293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.support.v7.widget.RecyclerView;
2393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.util.AttributeSet;
24b655b8850064cc4f8e59652b4e3bffc09090769aWinsonimport android.util.SparseIntArray;
25260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyalimport android.view.MotionEvent;
26f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chungimport android.view.View;
27b713ad4adb7d7dbc926ee2ab793ee6ef38cd2520Sunny Goyal
285f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chungimport com.android.launcher3.BaseRecyclerView;
29a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinsonimport com.android.launcher3.BubbleTextView;
305f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chungimport com.android.launcher3.DeviceProfile;
314ebc3d070ffa5ffda469aebcece20efda52d2028Hyunyoung Songimport com.android.launcher3.Launcher;
32fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport com.android.launcher3.R;
330fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschlerimport com.android.launcher3.config.FeatureFlags;
34260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyalimport com.android.launcher3.graphics.DrawableFactory;
356c46a6d324310bd2fc0ea223c9782ba6394512e7Sunny Goyalimport com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
3655c6691e3a2e953dc9882ad0bc0a4c1ee2d42e67Tony Wickham
3793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport java.util.List;
3893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
3993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung/**
40ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song * A RecyclerView with custom fast scroll support for the all apps view.
4193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */
4259a238095e82fd02355f4cb53abe01655a50b051Hyunyoung Songpublic class AllAppsRecyclerView extends BaseRecyclerView {
4393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
4493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    private AlphabeticalAppsList mApps;
45c088049113c261331b5685e64050d14a31cd72dfWinson    private AllAppsFastScrollHelper mFastScrollHelper;
4693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    private int mNumAppsPerRow;
47b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung
48b655b8850064cc4f8e59652b4e3bffc09090769aWinson    // The specific view heights that we use to calculate scroll
49b655b8850064cc4f8e59652b4e3bffc09090769aWinson    private SparseIntArray mViewHeights = new SparseIntArray();
50b655b8850064cc4f8e59652b4e3bffc09090769aWinson    private SparseIntArray mCachedScrollPositions = new SparseIntArray();
512e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen
52c088049113c261331b5685e64050d14a31cd72dfWinson    // The empty-search result background
53fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    private AllAppsBackgroundDrawable mEmptySearchBackground;
54fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    private int mEmptySearchBackgroundTopOffset;
55fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
560ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    private HeaderElevationController mElevationController;
570ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
585f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung    public AllAppsRecyclerView(Context context) {
5993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        this(context, null);
6093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
6193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
625f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung    public AllAppsRecyclerView(Context context, AttributeSet attrs) {
6393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        this(context, attrs, 0);
6493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
6593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
665f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung    public AllAppsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
6793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        this(context, attrs, defStyleAttr, 0);
6893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
6993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
705f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung    public AllAppsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr,
7193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung            int defStyleRes) {
7293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        super(context, attrs, defStyleAttr);
73fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        Resources res = getResources();
74c088049113c261331b5685e64050d14a31cd72dfWinson        addOnItemTouchListener(this);
75d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        mScrollbar.setDetachThumbOnFastScroll();
76fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        mEmptySearchBackgroundTopOffset = res.getDimensionPixelSize(
77fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson                R.dimen.all_apps_empty_search_bg_top_offset);
7893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
7993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
8093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
8193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     * Sets the list of apps in this view, used to determine the fastscroll position.
8293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
8393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    public void setApps(AlphabeticalAppsList apps) {
8493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        mApps = apps;
85c088049113c261331b5685e64050d14a31cd72dfWinson        mFastScrollHelper = new AllAppsFastScrollHelper(this, apps);
8693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
8793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
880ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public void setElevationController(HeaderElevationController elevationController) {
890ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        mElevationController = elevationController;
900ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
910ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
9293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
9393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     * Sets the number of apps per row in this recycler view.
9493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
951cddad6c6bff0b271e8ebde44013a5a09f273436Winson Chung    public void setNumAppsPerRow(DeviceProfile grid, int numAppsPerRow) {
96208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        mNumAppsPerRow = numAppsPerRow;
97da25da3d557177febb9c7afb78e04b1ef4a45f17Winson Chung
98da25da3d557177febb9c7afb78e04b1ef4a45f17Winson Chung        RecyclerView.RecycledViewPool pool = getRecycledViewPool();
99da25da3d557177febb9c7afb78e04b1ef4a45f17Winson Chung        int approxRows = (int) Math.ceil(grid.availableHeightPx / grid.allAppsIconSizePx);
100c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH, 1);
101c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_SEARCH_DIVIDER, 1);
102c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET_DIVIDER, 1);
103c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET, 1);
104c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_ICON, approxRows * mNumAppsPerRow);
105c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_PREDICTION_ICON, mNumAppsPerRow);
106c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_PREDICTION_DIVIDER, 1);
10793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
10893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
10993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
110b655b8850064cc4f8e59652b4e3bffc09090769aWinson     * Ensures that we can present a stable scrollbar for views of varying types by pre-measuring
111b655b8850064cc4f8e59652b4e3bffc09090769aWinson     * all the different view types.
112c088049113c261331b5685e64050d14a31cd72dfWinson     */
113b655b8850064cc4f8e59652b4e3bffc09090769aWinson    public void preMeasureViews(AllAppsGridAdapter adapter) {
1140fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        View icon = adapter.onCreateViewHolder(this, AllAppsGridAdapter.VIEW_TYPE_ICON).itemView;
1150fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        final int iconHeight = icon.getLayoutParams().height;
1160fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_ICON, iconHeight);
1170fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_PREDICTION_ICON, iconHeight);
1180fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler
119b655b8850064cc4f8e59652b4e3bffc09090769aWinson        final int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(
120b655b8850064cc4f8e59652b4e3bffc09090769aWinson                getResources().getDisplayMetrics().widthPixels, View.MeasureSpec.AT_MOST);
121b655b8850064cc4f8e59652b4e3bffc09090769aWinson        final int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(
122b655b8850064cc4f8e59652b4e3bffc09090769aWinson                getResources().getDisplayMetrics().heightPixels, View.MeasureSpec.AT_MOST);
123b655b8850064cc4f8e59652b4e3bffc09090769aWinson
1240fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        putSameHeightFor(adapter, widthMeasureSpec, heightMeasureSpec,
1250fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                AllAppsGridAdapter.VIEW_TYPE_PREDICTION_DIVIDER,
1260fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET_DIVIDER);
1270fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        putSameHeightFor(adapter, widthMeasureSpec, heightMeasureSpec,
1280fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                AllAppsGridAdapter.VIEW_TYPE_SEARCH_DIVIDER);
1290fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        putSameHeightFor(adapter, widthMeasureSpec, heightMeasureSpec,
1300fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET);
1310fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        putSameHeightFor(adapter, widthMeasureSpec, heightMeasureSpec,
1320fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH);
1330fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler
1340fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        if (FeatureFlags.DISCOVERY_ENABLED) {
1350fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            putSameHeightFor(adapter, widthMeasureSpec, heightMeasureSpec,
1360fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                    AllAppsGridAdapter.VIEW_TYPE_APPS_LOADING_DIVIDER);
1370fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            putSameHeightFor(adapter, widthMeasureSpec, heightMeasureSpec,
1380fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                    AllAppsGridAdapter.VIEW_TYPE_DISCOVERY_ITEM);
1390fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        }
1400fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    }
141b655b8850064cc4f8e59652b4e3bffc09090769aWinson
1420fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    private void putSameHeightFor(AllAppsGridAdapter adapter, int w, int h, int... viewTypes) {
1430fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        View view = adapter.onCreateViewHolder(this, viewTypes[0]).itemView;
1440fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        view.measure(w, h);
1450fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        for (int viewType : viewTypes) {
1460fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            mViewHeights.put(viewType, view.getMeasuredHeight());
1470fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        }
148c088049113c261331b5685e64050d14a31cd72dfWinson    }
149c088049113c261331b5685e64050d14a31cd72dfWinson
150c088049113c261331b5685e64050d14a31cd72dfWinson    /**
151ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung     * Scrolls this recycler view to the top.
152ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung     */
153ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung    public void scrollToTop() {
1542605900854a64eef49380332de17935d8204597dWinson        // Ensure we reattach the scrollbar if it was previously detached while fast-scrolling
1552605900854a64eef49380332de17935d8204597dWinson        if (mScrollbar.isThumbDetached()) {
1562605900854a64eef49380332de17935d8204597dWinson            mScrollbar.reattachThumbToScroll();
1572605900854a64eef49380332de17935d8204597dWinson        }
158ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung        scrollToPosition(0);
1590ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        if (mElevationController != null) {
1600ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            mElevationController.reset();
1610ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        }
16232f14071cc5808737c88da7b5f3047a8222f8843Winson Chung    }
16332f14071cc5808737c88da7b5f3047a8222f8843Winson Chung
16493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    @Override
165fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    public void onDraw(Canvas c) {
166fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        // Draw the background
167fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        if (mEmptySearchBackground != null && mEmptySearchBackground.getAlpha() > 0) {
168fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson            mEmptySearchBackground.draw(c);
169fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        }
170fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
171fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        super.onDraw(c);
172fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    }
173fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
174fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    @Override
175fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    protected boolean verifyDrawable(Drawable who) {
176fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        return who == mEmptySearchBackground || super.verifyDrawable(who);
177fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    }
178fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
179fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    @Override
180fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
181fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        updateEmptySearchBackgroundBounds();
182fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    }
183fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
18459a238095e82fd02355f4cb53abe01655a50b051Hyunyoung Song    public int getContainerType(View v) {
1858f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung        if (mApps.hasFilter()) {
1866c46a6d324310bd2fc0ea223c9782ba6394512e7Sunny Goyal            return ContainerType.SEARCHRESULT;
1878f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung        } else {
188a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson            if (v instanceof BubbleTextView) {
189a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                BubbleTextView icon = (BubbleTextView) v;
190a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                int position = getChildPosition(icon);
191a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                if (position != NO_POSITION) {
192a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                    List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
193a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                    AlphabeticalAppsList.AdapterItem item = items.get(position);
194c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller                    if (item.viewType == AllAppsGridAdapter.VIEW_TYPE_PREDICTION_ICON) {
1956c46a6d324310bd2fc0ea223c9782ba6394512e7Sunny Goyal                        return ContainerType.PREDICTION;
196a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                    }
197a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                }
198a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson            }
1996c46a6d324310bd2fc0ea223c9782ba6394512e7Sunny Goyal            return ContainerType.ALLAPPS;
2008f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung        }
2018f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung    }
2028f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung
203fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    public void onSearchResultsChanged() {
204fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        // Always scroll the view to the top so the user can see the changed results
205fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        scrollToTop();
206fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
2070fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        if (mApps.shouldShowEmptySearch()) {
208fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson            if (mEmptySearchBackground == null) {
209260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal                mEmptySearchBackground = DrawableFactory.get(getContext())
210260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal                        .getAllAppsBackground(getContext());
211fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson                mEmptySearchBackground.setAlpha(0);
212fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson                mEmptySearchBackground.setCallback(this);
213fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson                updateEmptySearchBackgroundBounds();
214fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson            }
215fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson            mEmptySearchBackground.animateBgAlpha(1f, 150);
216fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        } else if (mEmptySearchBackground != null) {
217fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson            // For the time being, we just immediately hide the background to ensure that it does
218fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson            // not overlap with the results
219fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson            mEmptySearchBackground.setBgAlpha(0f);
220fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        }
221fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    }
222fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
223260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal    @Override
224260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal    public boolean onInterceptTouchEvent(MotionEvent e) {
225260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal        boolean result = super.onInterceptTouchEvent(e);
226260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal        if (!result && e.getAction() == MotionEvent.ACTION_DOWN
227260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal                && mEmptySearchBackground != null && mEmptySearchBackground.getAlpha() > 0) {
228260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal            mEmptySearchBackground.setHotspot(e.getX(), e.getY());
229260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal        }
230260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal        return result;
231260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal    }
232260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal
23393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
23499d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung     * Maps the touch (from 0..1) to the adapter position that should be visible.
23593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
236ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song    @Override
237ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song    public String scrollToPositionAtProgress(float touchFraction) {
238b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        int rowCount = mApps.getNumAppRows();
239b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        if (rowCount == 0) {
2409121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung            return "";
2419121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung        }
24293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
243208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        // Stop the scroller if it is scrolling
244208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        stopScroll();
245208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung
246b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        // Find the fastscroll section that maps to this touch fraction
247b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        List<AlphabeticalAppsList.FastScrollSectionInfo> fastScrollSections =
248b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                mApps.getFastScrollerSections();
249b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        AlphabeticalAppsList.FastScrollSectionInfo lastInfo = fastScrollSections.get(0);
250c088049113c261331b5685e64050d14a31cd72dfWinson        for (int i = 1; i < fastScrollSections.size(); i++) {
251c088049113c261331b5685e64050d14a31cd72dfWinson            AlphabeticalAppsList.FastScrollSectionInfo info = fastScrollSections.get(i);
252c088049113c261331b5685e64050d14a31cd72dfWinson            if (info.touchFraction > touchFraction) {
253c088049113c261331b5685e64050d14a31cd72dfWinson                break;
254208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung            }
255c088049113c261331b5685e64050d14a31cd72dfWinson            lastInfo = info;
256208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        }
257208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung
258c088049113c261331b5685e64050d14a31cd72dfWinson        // Update the fast scroll
259b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int scrollY = getCurrentScrollY();
260b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int availableScrollHeight = getAvailableScrollHeight();
261c088049113c261331b5685e64050d14a31cd72dfWinson        mFastScrollHelper.smoothScrollToSection(scrollY, availableScrollHeight, lastInfo);
262b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        return lastInfo.sectionName;
263ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song    }
264ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song
265b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung    @Override
266b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung    public void onFastScrollCompleted() {
267b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        super.onFastScrollCompleted();
268c088049113c261331b5685e64050d14a31cd72dfWinson        mFastScrollHelper.onFastScrollCompleted();
269c088049113c261331b5685e64050d14a31cd72dfWinson    }
270c088049113c261331b5685e64050d14a31cd72dfWinson
271c088049113c261331b5685e64050d14a31cd72dfWinson    @Override
272c088049113c261331b5685e64050d14a31cd72dfWinson    public void setAdapter(Adapter adapter) {
273c088049113c261331b5685e64050d14a31cd72dfWinson        super.setAdapter(adapter);
274b655b8850064cc4f8e59652b4e3bffc09090769aWinson        adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
275b655b8850064cc4f8e59652b4e3bffc09090769aWinson            public void onChanged() {
276b655b8850064cc4f8e59652b4e3bffc09090769aWinson                mCachedScrollPositions.clear();
277b655b8850064cc4f8e59652b4e3bffc09090769aWinson            }
278b655b8850064cc4f8e59652b4e3bffc09090769aWinson        });
279c088049113c261331b5685e64050d14a31cd72dfWinson        mFastScrollHelper.onSetAdapter((AllAppsGridAdapter) adapter);
280ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song    }
281ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song
282f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chung    /**
283515f2897e876ba52ed6371d22e6d0f7d1016aaf3Winson Chung     * Updates the bounds for the scrollbar.
284f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chung     */
285ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song    @Override
286d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson    public void onUpdateScrollbar(int dy) {
28783f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung        List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
28883f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung
289ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Skip early if there are no items or we haven't been measured
290ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        if (items.isEmpty() || mNumAppsPerRow == 0) {
2915d9fb0e92f2ef2b25f3aa93c1f89838ccc68aa88Sunny Goyal            mScrollbar.setThumbOffsetY(-1);
292f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chung            return;
293f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chung        }
294f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chung
295b655b8850064cc4f8e59652b4e3bffc09090769aWinson        // Skip early if, there no child laid out in the container.
296b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int scrollY = getCurrentScrollY();
297b655b8850064cc4f8e59652b4e3bffc09090769aWinson        if (scrollY < 0) {
2985d9fb0e92f2ef2b25f3aa93c1f89838ccc68aa88Sunny Goyal            mScrollbar.setThumbOffsetY(-1);
299b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung            return;
300b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        }
301b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung
302d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        // Only show the scrollbar if there is height to be scrolled
303d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        int availableScrollBarHeight = getAvailableScrollBarHeight();
304b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int availableScrollHeight = getAvailableScrollHeight();
305d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        if (availableScrollHeight <= 0) {
3065d9fb0e92f2ef2b25f3aa93c1f89838ccc68aa88Sunny Goyal            mScrollbar.setThumbOffsetY(-1);
307d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson            return;
308d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        }
309d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson
310d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        if (mScrollbar.isThumbDetached()) {
311e8eaa9c94c5bfb9f103b486b24213e7dd86e8429Winson            if (!mScrollbar.isDraggingThumb()) {
312e8eaa9c94c5bfb9f103b486b24213e7dd86e8429Winson                // Calculate the current scroll position, the scrollY of the recycler view accounts
313e8eaa9c94c5bfb9f103b486b24213e7dd86e8429Winson                // for the view padding, while the scrollBarY is drawn right up to the background
314e8eaa9c94c5bfb9f103b486b24213e7dd86e8429Winson                // padding (ignoring padding)
31500e106880d33d2fc173c38e6d9da98762ccee478Sunny Goyal                int scrollBarY = (int)
31600e106880d33d2fc173c38e6d9da98762ccee478Sunny Goyal                        (((float) scrollY / availableScrollHeight) * availableScrollBarHeight);
317d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson
3185d9fb0e92f2ef2b25f3aa93c1f89838ccc68aa88Sunny Goyal                int thumbScrollY = mScrollbar.getThumbOffsetY();
319d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                int diffScrollY = scrollBarY - thumbScrollY;
320d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                if (diffScrollY * dy > 0f) {
321d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    // User is scrolling in the same direction the thumb needs to catch up to the
32251a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    // current scroll position.  We do this by mapping the difference in movement
32351a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    // from the original scroll bar position to the difference in movement necessary
32451a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    // in the detached thumb position to ensure that both speed towards the same
32551a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    // position at either end of the list.
32651a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    if (dy < 0) {
32751a7d965443373e3a9f4fce1c0895669ed4110bdWinson                        int offset = (int) ((dy * thumbScrollY) / (float) scrollBarY);
32851a7d965443373e3a9f4fce1c0895669ed4110bdWinson                        thumbScrollY += Math.max(offset, diffScrollY);
32951a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    } else {
33051a7d965443373e3a9f4fce1c0895669ed4110bdWinson                        int offset = (int) ((dy * (availableScrollBarHeight - thumbScrollY)) /
33151a7d965443373e3a9f4fce1c0895669ed4110bdWinson                                (float) (availableScrollBarHeight - scrollBarY));
33251a7d965443373e3a9f4fce1c0895669ed4110bdWinson                        thumbScrollY += Math.min(offset, diffScrollY);
33351a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    }
334d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    thumbScrollY = Math.max(0, Math.min(availableScrollBarHeight, thumbScrollY));
3355d9fb0e92f2ef2b25f3aa93c1f89838ccc68aa88Sunny Goyal                    mScrollbar.setThumbOffsetY(thumbScrollY);
336d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    if (scrollBarY == thumbScrollY) {
337d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                        mScrollbar.reattachThumbToScroll();
338d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    }
339d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                } else {
340d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    // User is scrolling in an opposite direction to the direction that the thumb
341d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    // needs to catch up to the scroll position.  Do nothing except for updating
342d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    // the scroll bar x to match the thumb width.
3435d9fb0e92f2ef2b25f3aa93c1f89838ccc68aa88Sunny Goyal                    mScrollbar.setThumbOffsetY(thumbScrollY);
344d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                }
345d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson            }
346d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        } else {
347b655b8850064cc4f8e59652b4e3bffc09090769aWinson            synchronizeScrollBarThumbOffsetToViewScroll(scrollY, availableScrollHeight);
348d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        }
349b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung    }
350f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chung
351b655b8850064cc4f8e59652b4e3bffc09090769aWinson    @Override
352b655b8850064cc4f8e59652b4e3bffc09090769aWinson    protected boolean supportsFastScrolling() {
353b655b8850064cc4f8e59652b4e3bffc09090769aWinson        // Only allow fast scrolling when the user is not searching, since the results are not
354b655b8850064cc4f8e59652b4e3bffc09090769aWinson        // grouped in a meaningful order
355b655b8850064cc4f8e59652b4e3bffc09090769aWinson        return !mApps.hasFilter();
356b655b8850064cc4f8e59652b4e3bffc09090769aWinson    }
357532e6ea2e6e4b5f968038b52db9bb998cb9fe84aWinson Chung
358b655b8850064cc4f8e59652b4e3bffc09090769aWinson    @Override
3592e22b5d2de066245f8c8f52343bb2a8b4e8eb563Peter Schiller    public int getCurrentScrollY() {
360ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Return early if there are no items or we haven't been measured
361d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
362b655b8850064cc4f8e59652b4e3bffc09090769aWinson        if (items.isEmpty() || mNumAppsPerRow == 0 || getChildCount() == 0) {
363b655b8850064cc4f8e59652b4e3bffc09090769aWinson            return -1;
364b655b8850064cc4f8e59652b4e3bffc09090769aWinson        }
365b655b8850064cc4f8e59652b4e3bffc09090769aWinson
366b655b8850064cc4f8e59652b4e3bffc09090769aWinson        // Calculate the y and offset for the item
367b655b8850064cc4f8e59652b4e3bffc09090769aWinson        View child = getChildAt(0);
368b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int position = getChildPosition(child);
369b655b8850064cc4f8e59652b4e3bffc09090769aWinson        if (position == NO_POSITION) {
370b655b8850064cc4f8e59652b4e3bffc09090769aWinson            return -1;
371532e6ea2e6e4b5f968038b52db9bb998cb9fe84aWinson Chung        }
372b655b8850064cc4f8e59652b4e3bffc09090769aWinson        return getCurrentScrollY(position, getLayoutManager().getDecoratedTop(child));
373b655b8850064cc4f8e59652b4e3bffc09090769aWinson    }
374532e6ea2e6e4b5f968038b52db9bb998cb9fe84aWinson Chung
375b655b8850064cc4f8e59652b4e3bffc09090769aWinson    public int getCurrentScrollY(int position, int offset) {
376b655b8850064cc4f8e59652b4e3bffc09090769aWinson        List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
377b655b8850064cc4f8e59652b4e3bffc09090769aWinson        AlphabeticalAppsList.AdapterItem posItem = position < items.size() ?
378b655b8850064cc4f8e59652b4e3bffc09090769aWinson                items.get(position) : null;
379b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int y = mCachedScrollPositions.get(position, -1);
380b655b8850064cc4f8e59652b4e3bffc09090769aWinson        if (y < 0) {
381b655b8850064cc4f8e59652b4e3bffc09090769aWinson            y = 0;
382b655b8850064cc4f8e59652b4e3bffc09090769aWinson            for (int i = 0; i < position; i++) {
383b655b8850064cc4f8e59652b4e3bffc09090769aWinson                AlphabeticalAppsList.AdapterItem item = items.get(i);
384b655b8850064cc4f8e59652b4e3bffc09090769aWinson                if (AllAppsGridAdapter.isIconViewType(item.viewType)) {
385b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    // Break once we reach the desired row
386b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    if (posItem != null && posItem.viewType == item.viewType &&
387b655b8850064cc4f8e59652b4e3bffc09090769aWinson                            posItem.rowIndex == item.rowIndex) {
388b655b8850064cc4f8e59652b4e3bffc09090769aWinson                        break;
389b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    }
390b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    // Otherwise, only account for the first icon in the row since they are the same
391b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    // size within a row
392b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    if (item.rowAppIndex == 0) {
393b655b8850064cc4f8e59652b4e3bffc09090769aWinson                        y += mViewHeights.get(item.viewType, 0);
394b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    }
395b655b8850064cc4f8e59652b4e3bffc09090769aWinson                } else {
396b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    // Rest of the views span the full width
397b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    y += mViewHeights.get(item.viewType, 0);
398ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung                }
399ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung            }
400b655b8850064cc4f8e59652b4e3bffc09090769aWinson            mCachedScrollPositions.put(position, y);
401ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung        }
402b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung
403b655b8850064cc4f8e59652b4e3bffc09090769aWinson        return getPaddingTop() + y - offset;
404646c236ad283c44e41747176fe1017d619b92d5aWinson    }
405646c236ad283c44e41747176fe1017d619b92d5aWinson
4064ebc3d070ffa5ffda469aebcece20efda52d2028Hyunyoung Song    @Override
40700e106880d33d2fc173c38e6d9da98762ccee478Sunny Goyal    protected int getScrollbarTrackHeight() {
40800e106880d33d2fc173c38e6d9da98762ccee478Sunny Goyal        return super.getScrollbarTrackHeight()
4094ebc3d070ffa5ffda469aebcece20efda52d2028Hyunyoung Song                - Launcher.getLauncher(getContext()).getDragLayer().getInsets().bottom;
4104ebc3d070ffa5ffda469aebcece20efda52d2028Hyunyoung Song    }
4114ebc3d070ffa5ffda469aebcece20efda52d2028Hyunyoung Song
412b655b8850064cc4f8e59652b4e3bffc09090769aWinson    /**
413b655b8850064cc4f8e59652b4e3bffc09090769aWinson     * Returns the available scroll height:
414b655b8850064cc4f8e59652b4e3bffc09090769aWinson     *   AvailableScrollHeight = Total height of the all items - last page height
415b655b8850064cc4f8e59652b4e3bffc09090769aWinson     */
416b655b8850064cc4f8e59652b4e3bffc09090769aWinson    @Override
417b655b8850064cc4f8e59652b4e3bffc09090769aWinson    protected int getAvailableScrollHeight() {
418b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int paddedHeight = getCurrentScrollY(mApps.getAdapterItems().size(), 0);
419b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int totalHeight = paddedHeight + getPaddingBottom();
42000e106880d33d2fc173c38e6d9da98762ccee478Sunny Goyal        return totalHeight - getScrollbarTrackHeight();
421b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung    }
422fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
423fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    /**
424fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson     * Updates the bounds of the empty search background.
425fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson     */
426fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    private void updateEmptySearchBackgroundBounds() {
427fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        if (mEmptySearchBackground == null) {
428fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson            return;
429fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        }
430fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
431fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        // Center the empty search background on this new view bounds
432fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        int x = (getMeasuredWidth() - mEmptySearchBackground.getIntrinsicWidth()) / 2;
433fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        int y = mEmptySearchBackgroundTopOffset;
434fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        mEmptySearchBackground.setBounds(x, y,
435fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson                x + mEmptySearchBackground.getIntrinsicWidth(),
436fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson                y + mEmptySearchBackground.getIntrinsicHeight());
437fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    }
4380fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler
43993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung}
440