AllAppsRecyclerView.java revision 6c46a6d324310bd2fc0ea223c9782ba6394512e7
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;
25f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chungimport android.view.View;
26b713ad4adb7d7dbc926ee2ab793ee6ef38cd2520Sunny Goyal
275f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chungimport com.android.launcher3.BaseRecyclerView;
28a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinsonimport com.android.launcher3.BubbleTextView;
295f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chungimport com.android.launcher3.DeviceProfile;
304ebc3d070ffa5ffda469aebcece20efda52d2028Hyunyoung Songimport com.android.launcher3.Launcher;
31fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport com.android.launcher3.R;
326c46a6d324310bd2fc0ea223c9782ba6394512e7Sunny Goyalimport com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
3355c6691e3a2e953dc9882ad0bc0a4c1ee2d42e67Tony Wickham
3493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport java.util.List;
3593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
3693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung/**
37ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song * A RecyclerView with custom fast scroll support for the all apps view.
3893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */
3959a238095e82fd02355f4cb53abe01655a50b051Hyunyoung Songpublic class AllAppsRecyclerView extends BaseRecyclerView {
4093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
4193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    private AlphabeticalAppsList mApps;
42c088049113c261331b5685e64050d14a31cd72dfWinson    private AllAppsFastScrollHelper mFastScrollHelper;
4393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    private int mNumAppsPerRow;
44b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung
45b655b8850064cc4f8e59652b4e3bffc09090769aWinson    // The specific view heights that we use to calculate scroll
46b655b8850064cc4f8e59652b4e3bffc09090769aWinson    private SparseIntArray mViewHeights = new SparseIntArray();
47b655b8850064cc4f8e59652b4e3bffc09090769aWinson    private SparseIntArray mCachedScrollPositions = new SparseIntArray();
482e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen
49c088049113c261331b5685e64050d14a31cd72dfWinson    // The empty-search result background
50fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    private AllAppsBackgroundDrawable mEmptySearchBackground;
51fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    private int mEmptySearchBackgroundTopOffset;
52fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
530ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    private HeaderElevationController mElevationController;
540ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
555f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung    public AllAppsRecyclerView(Context context) {
5693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        this(context, null);
5793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
5893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
595f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung    public AllAppsRecyclerView(Context context, AttributeSet attrs) {
6093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        this(context, attrs, 0);
6193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
6293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
635f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung    public AllAppsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
6493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        this(context, attrs, defStyleAttr, 0);
6593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
6693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
675f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung    public AllAppsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr,
6893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung            int defStyleRes) {
6993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        super(context, attrs, defStyleAttr);
70fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        Resources res = getResources();
71c088049113c261331b5685e64050d14a31cd72dfWinson        addOnItemTouchListener(this);
72d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        mScrollbar.setDetachThumbOnFastScroll();
73fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        mEmptySearchBackgroundTopOffset = res.getDimensionPixelSize(
74fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson                R.dimen.all_apps_empty_search_bg_top_offset);
7593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
7693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
7793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
7893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     * Sets the list of apps in this view, used to determine the fastscroll position.
7993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
8093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    public void setApps(AlphabeticalAppsList apps) {
8193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        mApps = apps;
82c088049113c261331b5685e64050d14a31cd72dfWinson        mFastScrollHelper = new AllAppsFastScrollHelper(this, apps);
8393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
8493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
850ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    public void setElevationController(HeaderElevationController elevationController) {
860ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        mElevationController = elevationController;
870ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal    }
880ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal
8993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
9093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     * Sets the number of apps per row in this recycler view.
9193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
921cddad6c6bff0b271e8ebde44013a5a09f273436Winson Chung    public void setNumAppsPerRow(DeviceProfile grid, int numAppsPerRow) {
93208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        mNumAppsPerRow = numAppsPerRow;
94da25da3d557177febb9c7afb78e04b1ef4a45f17Winson Chung
95da25da3d557177febb9c7afb78e04b1ef4a45f17Winson Chung        RecyclerView.RecycledViewPool pool = getRecycledViewPool();
96da25da3d557177febb9c7afb78e04b1ef4a45f17Winson Chung        int approxRows = (int) Math.ceil(grid.availableHeightPx / grid.allAppsIconSizePx);
97c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH, 1);
98c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_SEARCH_DIVIDER, 1);
99c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET_DIVIDER, 1);
100c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET, 1);
101c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_ICON, approxRows * mNumAppsPerRow);
102c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_PREDICTION_ICON, mNumAppsPerRow);
103c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_PREDICTION_DIVIDER, 1);
10493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
10593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
10693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
107b655b8850064cc4f8e59652b4e3bffc09090769aWinson     * Ensures that we can present a stable scrollbar for views of varying types by pre-measuring
108b655b8850064cc4f8e59652b4e3bffc09090769aWinson     * all the different view types.
109c088049113c261331b5685e64050d14a31cd72dfWinson     */
110b655b8850064cc4f8e59652b4e3bffc09090769aWinson    public void preMeasureViews(AllAppsGridAdapter adapter) {
111b655b8850064cc4f8e59652b4e3bffc09090769aWinson        final int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(
112b655b8850064cc4f8e59652b4e3bffc09090769aWinson                getResources().getDisplayMetrics().widthPixels, View.MeasureSpec.AT_MOST);
113b655b8850064cc4f8e59652b4e3bffc09090769aWinson        final int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(
114b655b8850064cc4f8e59652b4e3bffc09090769aWinson                getResources().getDisplayMetrics().heightPixels, View.MeasureSpec.AT_MOST);
115b655b8850064cc4f8e59652b4e3bffc09090769aWinson
116b655b8850064cc4f8e59652b4e3bffc09090769aWinson        // Icons
117b655b8850064cc4f8e59652b4e3bffc09090769aWinson        BubbleTextView icon = (BubbleTextView) adapter.onCreateViewHolder(this,
1182a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal                AllAppsGridAdapter.VIEW_TYPE_ICON).itemView;
1191f06427266c0cb5de4561fc7c620ff542f625300Winson        int iconHeight = icon.getLayoutParams().height;
1201f06427266c0cb5de4561fc7c620ff542f625300Winson        mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_ICON, iconHeight);
1211f06427266c0cb5de4561fc7c620ff542f625300Winson        mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_PREDICTION_ICON, iconHeight);
122b655b8850064cc4f8e59652b4e3bffc09090769aWinson
123b655b8850064cc4f8e59652b4e3bffc09090769aWinson        // Search divider
124b655b8850064cc4f8e59652b4e3bffc09090769aWinson        View searchDivider = adapter.onCreateViewHolder(this,
1252a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal                AllAppsGridAdapter.VIEW_TYPE_SEARCH_DIVIDER).itemView;
126b655b8850064cc4f8e59652b4e3bffc09090769aWinson        searchDivider.measure(widthMeasureSpec, heightMeasureSpec);
127b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int searchDividerHeight = searchDivider.getMeasuredHeight();
128b655b8850064cc4f8e59652b4e3bffc09090769aWinson        mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_SEARCH_DIVIDER, searchDividerHeight);
129b655b8850064cc4f8e59652b4e3bffc09090769aWinson
130b655b8850064cc4f8e59652b4e3bffc09090769aWinson        // Generic dividers
131b655b8850064cc4f8e59652b4e3bffc09090769aWinson        View divider = adapter.onCreateViewHolder(this,
1322a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal                AllAppsGridAdapter.VIEW_TYPE_PREDICTION_DIVIDER).itemView;
133b655b8850064cc4f8e59652b4e3bffc09090769aWinson        divider.measure(widthMeasureSpec, heightMeasureSpec);
134b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int dividerHeight = divider.getMeasuredHeight();
135b655b8850064cc4f8e59652b4e3bffc09090769aWinson        mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_PREDICTION_DIVIDER, dividerHeight);
136b655b8850064cc4f8e59652b4e3bffc09090769aWinson        mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET_DIVIDER, dividerHeight);
137b655b8850064cc4f8e59652b4e3bffc09090769aWinson
138b655b8850064cc4f8e59652b4e3bffc09090769aWinson        // Search views
139b655b8850064cc4f8e59652b4e3bffc09090769aWinson        View emptySearch = adapter.onCreateViewHolder(this,
1402a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal                AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH).itemView;
141b655b8850064cc4f8e59652b4e3bffc09090769aWinson        emptySearch.measure(widthMeasureSpec, heightMeasureSpec);
142b655b8850064cc4f8e59652b4e3bffc09090769aWinson        mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH,
143b655b8850064cc4f8e59652b4e3bffc09090769aWinson                emptySearch.getMeasuredHeight());
144b655b8850064cc4f8e59652b4e3bffc09090769aWinson        View searchMarket = adapter.onCreateViewHolder(this,
1452a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal                AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET).itemView;
146b655b8850064cc4f8e59652b4e3bffc09090769aWinson        searchMarket.measure(widthMeasureSpec, heightMeasureSpec);
147b655b8850064cc4f8e59652b4e3bffc09090769aWinson        mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET,
148b655b8850064cc4f8e59652b4e3bffc09090769aWinson                searchMarket.getMeasuredHeight());
149c088049113c261331b5685e64050d14a31cd72dfWinson    }
150c088049113c261331b5685e64050d14a31cd72dfWinson
151c088049113c261331b5685e64050d14a31cd72dfWinson    /**
152ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung     * Scrolls this recycler view to the top.
153ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung     */
154ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung    public void scrollToTop() {
1552605900854a64eef49380332de17935d8204597dWinson        // Ensure we reattach the scrollbar if it was previously detached while fast-scrolling
1562605900854a64eef49380332de17935d8204597dWinson        if (mScrollbar.isThumbDetached()) {
1572605900854a64eef49380332de17935d8204597dWinson            mScrollbar.reattachThumbToScroll();
1582605900854a64eef49380332de17935d8204597dWinson        }
159ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung        scrollToPosition(0);
1600ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        if (mElevationController != null) {
1610ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal            mElevationController.reset();
1620ac7ede56afebe4401c0636196f5844be573ad68Sunny Goyal        }
16332f14071cc5808737c88da7b5f3047a8222f8843Winson Chung    }
16432f14071cc5808737c88da7b5f3047a8222f8843Winson Chung
16593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    @Override
166fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    public void onDraw(Canvas c) {
167fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        // Draw the background
168fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        if (mEmptySearchBackground != null && mEmptySearchBackground.getAlpha() > 0) {
169fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson            mEmptySearchBackground.draw(c);
170fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        }
171fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
172fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        super.onDraw(c);
173fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    }
174fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
175fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    @Override
176fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    protected boolean verifyDrawable(Drawable who) {
177fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        return who == mEmptySearchBackground || super.verifyDrawable(who);
178fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    }
179fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
180fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    @Override
181fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
182fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        updateEmptySearchBackgroundBounds();
183fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    }
184fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
18559a238095e82fd02355f4cb53abe01655a50b051Hyunyoung Song    public int getContainerType(View v) {
1868f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung        if (mApps.hasFilter()) {
1876c46a6d324310bd2fc0ea223c9782ba6394512e7Sunny Goyal            return ContainerType.SEARCHRESULT;
1888f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung        } else {
189a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson            if (v instanceof BubbleTextView) {
190a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                BubbleTextView icon = (BubbleTextView) v;
191a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                int position = getChildPosition(icon);
192a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                if (position != NO_POSITION) {
193a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                    List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
194a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                    AlphabeticalAppsList.AdapterItem item = items.get(position);
195c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller                    if (item.viewType == AllAppsGridAdapter.VIEW_TYPE_PREDICTION_ICON) {
1966c46a6d324310bd2fc0ea223c9782ba6394512e7Sunny Goyal                        return ContainerType.PREDICTION;
197a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                    }
198a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson                }
199a49b1f75cdf8efe88408173737a7b3c8f4b58a4cWinson            }
2006c46a6d324310bd2fc0ea223c9782ba6394512e7Sunny Goyal            return ContainerType.ALLAPPS;
2018f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung        }
2028f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung    }
2038f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung
204fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    public void onSearchResultsChanged() {
205fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        // Always scroll the view to the top so the user can see the changed results
206fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        scrollToTop();
207fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
208fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        if (mApps.hasNoFilteredResults()) {
209fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson            if (mEmptySearchBackground == null) {
210fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson                mEmptySearchBackground = new AllAppsBackgroundDrawable(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
22393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
22499d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung     * Maps the touch (from 0..1) to the adapter position that should be visible.
22593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
226ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song    @Override
227ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song    public String scrollToPositionAtProgress(float touchFraction) {
228b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        int rowCount = mApps.getNumAppRows();
229b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        if (rowCount == 0) {
2309121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung            return "";
2319121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung        }
23293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
233208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        // Stop the scroller if it is scrolling
234208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        stopScroll();
235208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung
236b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        // Find the fastscroll section that maps to this touch fraction
237b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        List<AlphabeticalAppsList.FastScrollSectionInfo> fastScrollSections =
238b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                mApps.getFastScrollerSections();
239b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        AlphabeticalAppsList.FastScrollSectionInfo lastInfo = fastScrollSections.get(0);
240c088049113c261331b5685e64050d14a31cd72dfWinson        for (int i = 1; i < fastScrollSections.size(); i++) {
241c088049113c261331b5685e64050d14a31cd72dfWinson            AlphabeticalAppsList.FastScrollSectionInfo info = fastScrollSections.get(i);
242c088049113c261331b5685e64050d14a31cd72dfWinson            if (info.touchFraction > touchFraction) {
243c088049113c261331b5685e64050d14a31cd72dfWinson                break;
244208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung            }
245c088049113c261331b5685e64050d14a31cd72dfWinson            lastInfo = info;
246208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        }
247208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung
248c088049113c261331b5685e64050d14a31cd72dfWinson        // Update the fast scroll
249b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int scrollY = getCurrentScrollY();
250b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int availableScrollHeight = getAvailableScrollHeight();
251c088049113c261331b5685e64050d14a31cd72dfWinson        mFastScrollHelper.smoothScrollToSection(scrollY, availableScrollHeight, lastInfo);
252b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        return lastInfo.sectionName;
253ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song    }
254ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song
255b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung    @Override
256b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung    public void onFastScrollCompleted() {
257b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        super.onFastScrollCompleted();
258c088049113c261331b5685e64050d14a31cd72dfWinson        mFastScrollHelper.onFastScrollCompleted();
259c088049113c261331b5685e64050d14a31cd72dfWinson    }
260c088049113c261331b5685e64050d14a31cd72dfWinson
261c088049113c261331b5685e64050d14a31cd72dfWinson    @Override
262c088049113c261331b5685e64050d14a31cd72dfWinson    public void setAdapter(Adapter adapter) {
263c088049113c261331b5685e64050d14a31cd72dfWinson        super.setAdapter(adapter);
264b655b8850064cc4f8e59652b4e3bffc09090769aWinson        adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
265b655b8850064cc4f8e59652b4e3bffc09090769aWinson            public void onChanged() {
266b655b8850064cc4f8e59652b4e3bffc09090769aWinson                mCachedScrollPositions.clear();
267b655b8850064cc4f8e59652b4e3bffc09090769aWinson            }
268b655b8850064cc4f8e59652b4e3bffc09090769aWinson        });
269c088049113c261331b5685e64050d14a31cd72dfWinson        mFastScrollHelper.onSetAdapter((AllAppsGridAdapter) adapter);
270ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song    }
271ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song
272f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chung    /**
273515f2897e876ba52ed6371d22e6d0f7d1016aaf3Winson Chung     * Updates the bounds for the scrollbar.
274f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chung     */
275ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song    @Override
276d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson    public void onUpdateScrollbar(int dy) {
27783f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung        List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
27883f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung
279ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Skip early if there are no items or we haven't been measured
280ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        if (items.isEmpty() || mNumAppsPerRow == 0) {
2815d9fb0e92f2ef2b25f3aa93c1f89838ccc68aa88Sunny Goyal            mScrollbar.setThumbOffsetY(-1);
282f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chung            return;
283f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chung        }
284f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chung
285b655b8850064cc4f8e59652b4e3bffc09090769aWinson        // Skip early if, there no child laid out in the container.
286b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int scrollY = getCurrentScrollY();
287b655b8850064cc4f8e59652b4e3bffc09090769aWinson        if (scrollY < 0) {
2885d9fb0e92f2ef2b25f3aa93c1f89838ccc68aa88Sunny Goyal            mScrollbar.setThumbOffsetY(-1);
289b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung            return;
290b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        }
291b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung
292d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        // Only show the scrollbar if there is height to be scrolled
293d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        int availableScrollBarHeight = getAvailableScrollBarHeight();
294b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int availableScrollHeight = getAvailableScrollHeight();
295d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        if (availableScrollHeight <= 0) {
2965d9fb0e92f2ef2b25f3aa93c1f89838ccc68aa88Sunny Goyal            mScrollbar.setThumbOffsetY(-1);
297d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson            return;
298d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        }
299d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson
300d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        if (mScrollbar.isThumbDetached()) {
301e8eaa9c94c5bfb9f103b486b24213e7dd86e8429Winson            if (!mScrollbar.isDraggingThumb()) {
302e8eaa9c94c5bfb9f103b486b24213e7dd86e8429Winson                // Calculate the current scroll position, the scrollY of the recycler view accounts
303e8eaa9c94c5bfb9f103b486b24213e7dd86e8429Winson                // for the view padding, while the scrollBarY is drawn right up to the background
304e8eaa9c94c5bfb9f103b486b24213e7dd86e8429Winson                // padding (ignoring padding)
30500e106880d33d2fc173c38e6d9da98762ccee478Sunny Goyal                int scrollBarY = (int)
30600e106880d33d2fc173c38e6d9da98762ccee478Sunny Goyal                        (((float) scrollY / availableScrollHeight) * availableScrollBarHeight);
307d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson
3085d9fb0e92f2ef2b25f3aa93c1f89838ccc68aa88Sunny Goyal                int thumbScrollY = mScrollbar.getThumbOffsetY();
309d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                int diffScrollY = scrollBarY - thumbScrollY;
310d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                if (diffScrollY * dy > 0f) {
311d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    // User is scrolling in the same direction the thumb needs to catch up to the
31251a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    // current scroll position.  We do this by mapping the difference in movement
31351a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    // from the original scroll bar position to the difference in movement necessary
31451a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    // in the detached thumb position to ensure that both speed towards the same
31551a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    // position at either end of the list.
31651a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    if (dy < 0) {
31751a7d965443373e3a9f4fce1c0895669ed4110bdWinson                        int offset = (int) ((dy * thumbScrollY) / (float) scrollBarY);
31851a7d965443373e3a9f4fce1c0895669ed4110bdWinson                        thumbScrollY += Math.max(offset, diffScrollY);
31951a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    } else {
32051a7d965443373e3a9f4fce1c0895669ed4110bdWinson                        int offset = (int) ((dy * (availableScrollBarHeight - thumbScrollY)) /
32151a7d965443373e3a9f4fce1c0895669ed4110bdWinson                                (float) (availableScrollBarHeight - scrollBarY));
32251a7d965443373e3a9f4fce1c0895669ed4110bdWinson                        thumbScrollY += Math.min(offset, diffScrollY);
32351a7d965443373e3a9f4fce1c0895669ed4110bdWinson                    }
324d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    thumbScrollY = Math.max(0, Math.min(availableScrollBarHeight, thumbScrollY));
3255d9fb0e92f2ef2b25f3aa93c1f89838ccc68aa88Sunny Goyal                    mScrollbar.setThumbOffsetY(thumbScrollY);
326d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    if (scrollBarY == thumbScrollY) {
327d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                        mScrollbar.reattachThumbToScroll();
328d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    }
329d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                } else {
330d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    // User is scrolling in an opposite direction to the direction that the thumb
331d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    // needs to catch up to the scroll position.  Do nothing except for updating
332d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    // the scroll bar x to match the thumb width.
3335d9fb0e92f2ef2b25f3aa93c1f89838ccc68aa88Sunny Goyal                    mScrollbar.setThumbOffsetY(thumbScrollY);
334d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                }
335d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson            }
336d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        } else {
337b655b8850064cc4f8e59652b4e3bffc09090769aWinson            synchronizeScrollBarThumbOffsetToViewScroll(scrollY, availableScrollHeight);
338d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        }
339b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung    }
340f819dc2bc782e93ac9ecc163a99af0da62821d31Winson Chung
341b655b8850064cc4f8e59652b4e3bffc09090769aWinson    @Override
342b655b8850064cc4f8e59652b4e3bffc09090769aWinson    protected boolean supportsFastScrolling() {
343b655b8850064cc4f8e59652b4e3bffc09090769aWinson        // Only allow fast scrolling when the user is not searching, since the results are not
344b655b8850064cc4f8e59652b4e3bffc09090769aWinson        // grouped in a meaningful order
345b655b8850064cc4f8e59652b4e3bffc09090769aWinson        return !mApps.hasFilter();
346b655b8850064cc4f8e59652b4e3bffc09090769aWinson    }
347532e6ea2e6e4b5f968038b52db9bb998cb9fe84aWinson Chung
348b655b8850064cc4f8e59652b4e3bffc09090769aWinson    @Override
3492e22b5d2de066245f8c8f52343bb2a8b4e8eb563Peter Schiller    public int getCurrentScrollY() {
350ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        // Return early if there are no items or we haven't been measured
351d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
352b655b8850064cc4f8e59652b4e3bffc09090769aWinson        if (items.isEmpty() || mNumAppsPerRow == 0 || getChildCount() == 0) {
353b655b8850064cc4f8e59652b4e3bffc09090769aWinson            return -1;
354b655b8850064cc4f8e59652b4e3bffc09090769aWinson        }
355b655b8850064cc4f8e59652b4e3bffc09090769aWinson
356b655b8850064cc4f8e59652b4e3bffc09090769aWinson        // Calculate the y and offset for the item
357b655b8850064cc4f8e59652b4e3bffc09090769aWinson        View child = getChildAt(0);
358b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int position = getChildPosition(child);
359b655b8850064cc4f8e59652b4e3bffc09090769aWinson        if (position == NO_POSITION) {
360b655b8850064cc4f8e59652b4e3bffc09090769aWinson            return -1;
361532e6ea2e6e4b5f968038b52db9bb998cb9fe84aWinson Chung        }
362b655b8850064cc4f8e59652b4e3bffc09090769aWinson        return getCurrentScrollY(position, getLayoutManager().getDecoratedTop(child));
363b655b8850064cc4f8e59652b4e3bffc09090769aWinson    }
364532e6ea2e6e4b5f968038b52db9bb998cb9fe84aWinson Chung
365b655b8850064cc4f8e59652b4e3bffc09090769aWinson    public int getCurrentScrollY(int position, int offset) {
366b655b8850064cc4f8e59652b4e3bffc09090769aWinson        List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
367b655b8850064cc4f8e59652b4e3bffc09090769aWinson        AlphabeticalAppsList.AdapterItem posItem = position < items.size() ?
368b655b8850064cc4f8e59652b4e3bffc09090769aWinson                items.get(position) : null;
369b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int y = mCachedScrollPositions.get(position, -1);
370b655b8850064cc4f8e59652b4e3bffc09090769aWinson        if (y < 0) {
371b655b8850064cc4f8e59652b4e3bffc09090769aWinson            y = 0;
372b655b8850064cc4f8e59652b4e3bffc09090769aWinson            for (int i = 0; i < position; i++) {
373b655b8850064cc4f8e59652b4e3bffc09090769aWinson                AlphabeticalAppsList.AdapterItem item = items.get(i);
374b655b8850064cc4f8e59652b4e3bffc09090769aWinson                if (AllAppsGridAdapter.isIconViewType(item.viewType)) {
375b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    // Break once we reach the desired row
376b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    if (posItem != null && posItem.viewType == item.viewType &&
377b655b8850064cc4f8e59652b4e3bffc09090769aWinson                            posItem.rowIndex == item.rowIndex) {
378b655b8850064cc4f8e59652b4e3bffc09090769aWinson                        break;
379b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    }
380b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    // Otherwise, only account for the first icon in the row since they are the same
381b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    // size within a row
382b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    if (item.rowAppIndex == 0) {
383b655b8850064cc4f8e59652b4e3bffc09090769aWinson                        y += mViewHeights.get(item.viewType, 0);
384b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    }
385b655b8850064cc4f8e59652b4e3bffc09090769aWinson                } else {
386b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    // Rest of the views span the full width
387b655b8850064cc4f8e59652b4e3bffc09090769aWinson                    y += mViewHeights.get(item.viewType, 0);
388ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung                }
389ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung            }
390b655b8850064cc4f8e59652b4e3bffc09090769aWinson            mCachedScrollPositions.put(position, y);
391ed0c1cc739d3b3d82c301299db8abc3146de49bbWinson Chung        }
392b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung
393b655b8850064cc4f8e59652b4e3bffc09090769aWinson        return getPaddingTop() + y - offset;
394646c236ad283c44e41747176fe1017d619b92d5aWinson    }
395646c236ad283c44e41747176fe1017d619b92d5aWinson
3964ebc3d070ffa5ffda469aebcece20efda52d2028Hyunyoung Song    @Override
39700e106880d33d2fc173c38e6d9da98762ccee478Sunny Goyal    protected int getScrollbarTrackHeight() {
39800e106880d33d2fc173c38e6d9da98762ccee478Sunny Goyal        return super.getScrollbarTrackHeight()
3994ebc3d070ffa5ffda469aebcece20efda52d2028Hyunyoung Song                - Launcher.getLauncher(getContext()).getDragLayer().getInsets().bottom;
4004ebc3d070ffa5ffda469aebcece20efda52d2028Hyunyoung Song    }
4014ebc3d070ffa5ffda469aebcece20efda52d2028Hyunyoung Song
402b655b8850064cc4f8e59652b4e3bffc09090769aWinson    /**
403b655b8850064cc4f8e59652b4e3bffc09090769aWinson     * Returns the available scroll height:
404b655b8850064cc4f8e59652b4e3bffc09090769aWinson     *   AvailableScrollHeight = Total height of the all items - last page height
405b655b8850064cc4f8e59652b4e3bffc09090769aWinson     */
406b655b8850064cc4f8e59652b4e3bffc09090769aWinson    @Override
407b655b8850064cc4f8e59652b4e3bffc09090769aWinson    protected int getAvailableScrollHeight() {
408b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int paddedHeight = getCurrentScrollY(mApps.getAdapterItems().size(), 0);
409b655b8850064cc4f8e59652b4e3bffc09090769aWinson        int totalHeight = paddedHeight + getPaddingBottom();
41000e106880d33d2fc173c38e6d9da98762ccee478Sunny Goyal        return totalHeight - getScrollbarTrackHeight();
411b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung    }
412fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
413fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    /**
414fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson     * Updates the bounds of the empty search background.
415fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson     */
416fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    private void updateEmptySearchBackgroundBounds() {
417fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        if (mEmptySearchBackground == null) {
418fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson            return;
419fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        }
420fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson
421fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        // Center the empty search background on this new view bounds
422fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        int x = (getMeasuredWidth() - mEmptySearchBackground.getIntrinsicWidth()) / 2;
423fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        int y = mEmptySearchBackgroundTopOffset;
424fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson        mEmptySearchBackground.setBounds(x, y,
425fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson                x + mEmptySearchBackground.getIntrinsicWidth(),
426fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson                y + mEmptySearchBackground.getIntrinsicHeight());
427fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson    }
42893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung}
429