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