AllAppsRecyclerView.java revision 93f98eaf1800024cb2f28379bdd997f3debae63a
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 */ 1693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungpackage com.android.launcher3; 1793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 1893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.animation.ObjectAnimator; 1993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.content.Context; 2093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.content.res.Resources; 2193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.graphics.Canvas; 2293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.graphics.Color; 2393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.graphics.Paint; 2493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.graphics.Rect; 2593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.graphics.drawable.Drawable; 2693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.support.v7.widget.RecyclerView; 2793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.util.AttributeSet; 2893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.view.MotionEvent; 2993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.view.ViewConfiguration; 3093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 3193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport java.util.List; 3293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 3393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung/** 3493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * A RecyclerView with custom fastscroll support. This is the main container for the all apps 3593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * icons. 3693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */ 3793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungpublic class AppsContainerRecyclerView extends RecyclerView 3893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung implements RecyclerView.OnItemTouchListener { 3993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 4093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private AlphabeticalAppsList mApps; 4193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private int mNumAppsPerRow; 4293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 4393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private Drawable mFastScrollerBg; 4493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private boolean mDraggingFastScroller; 4593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private String mFastScrollSectionName; 4693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private Paint mFastScrollTextPaint; 4793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private Rect mFastScrollTextBounds = new Rect(); 4893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private float mFastScrollAlpha; 4993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private int mDownX; 5093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private int mDownY; 5193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private int mLastX; 5293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private int mLastY; 5393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private int mGutterSize; 5493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 5593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung public AppsContainerRecyclerView(Context context) { 5693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung this(context, null); 5793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 5893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 5993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung public AppsContainerRecyclerView(Context context, AttributeSet attrs) { 6093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung this(context, attrs, 0); 6193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 6293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 6393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung public AppsContainerRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) { 6493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung this(context, attrs, defStyleAttr, 0); 6593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 6693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 6793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung public AppsContainerRecyclerView(Context context, AttributeSet attrs, int defStyleAttr, 6893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int defStyleRes) { 6993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung super(context, attrs, defStyleAttr); 7093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 7193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung Resources res = context.getResources(); 7293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int fastScrollerSize = res.getDimensionPixelSize(R.dimen.apps_view_fast_scroll_popup_size); 7393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollerBg = res.getDrawable(R.drawable.apps_list_fastscroll_bg); 7493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollerBg.setBounds(0, 0, fastScrollerSize, fastScrollerSize); 7593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollTextPaint = new Paint(); 7693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollTextPaint.setColor(Color.WHITE); 7793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollTextPaint.setAntiAlias(true); 7893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollTextPaint.setTextSize(res.getDimensionPixelSize( 7993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung R.dimen.apps_view_fast_scroll_text_size)); 8093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mGutterSize = res.getDimensionPixelSize(R.dimen.apps_view_fast_scroll_gutter_size); 8193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung setFastScrollerAlpha(getFastScrollerAlpha()); 8293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 8393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 8493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung /** 8593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * Sets the list of apps in this view, used to determine the fastscroll position. 8693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */ 8793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung public void setApps(AlphabeticalAppsList apps) { 8893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mApps = apps; 8993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 9093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 9193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung /** 9293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * Sets the number of apps per row in this recycler view. 9393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */ 9493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung public void setNumAppsPerRow(int rowSize) { 9593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mNumAppsPerRow = rowSize; 9693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 9793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 9893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung /** 9993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * Sets the fast scroller alpha. 10093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */ 10193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung public void setFastScrollerAlpha(float alpha) { 10293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollAlpha = alpha; 10393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung invalidateFastScroller(); 10493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 10593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 10693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung /** 10793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * Gets the fast scroller alpha. 10893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */ 10993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung public float getFastScrollerAlpha() { 11093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung return mFastScrollAlpha; 11193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 11293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 11393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung @Override 11493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung protected void onFinishInflate() { 11593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung addOnItemTouchListener(this); 11693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 11793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 11893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung @Override 11993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung protected void dispatchDraw(Canvas canvas) { 12093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung super.dispatchDraw(canvas); 12193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 12293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung if (mFastScrollAlpha > 0f) { 12393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung boolean isRtl = (getResources().getConfiguration().getLayoutDirection() == 12493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung LAYOUT_DIRECTION_RTL); 12593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung Rect bgBounds = mFastScrollerBg.getBounds(); 12693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int restoreCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); 12793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int x; 12893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung if (isRtl) { 12993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung x = getPaddingLeft() + getScrollBarSize(); 13093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } else { 13193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung x = getWidth() - getPaddingRight() - getScrollBarSize() - bgBounds.width(); 13293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 13393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int y = mLastY - bgBounds.height() / 2; 13493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung y = Math.max(getPaddingTop(), Math.min(y, getHeight() - getPaddingBottom() - 13593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung bgBounds.height())); 13693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung canvas.translate(x, y); 13793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollerBg.setAlpha((int) (mFastScrollAlpha * 255)); 13893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollerBg.draw(canvas); 13993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollTextPaint.setAlpha((int) (mFastScrollAlpha * 255)); 14093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollTextPaint.getTextBounds(mFastScrollSectionName, 0, 14193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollSectionName.length(), mFastScrollTextBounds); 14293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung canvas.drawText(mFastScrollSectionName, 14393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung (bgBounds.width() - mFastScrollTextBounds.width()) / 2, 14493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung bgBounds.height() - (bgBounds.height() - mFastScrollTextBounds.height()) / 2, 14593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollTextPaint); 14693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung canvas.restoreToCount(restoreCount); 14793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 14893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 14993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 15093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung /** 15193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * We intercept the touch handling only to support fast scrolling when initiated from the 15293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * gutter. Otherwise, we fall back to the default RecyclerView touch handling. 15393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */ 15493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung @Override 15593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent ev) { 15693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung return handleTouchEvent(ev); 15793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 15893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 15993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung @Override 16093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung public void onTouchEvent(RecyclerView rv, MotionEvent ev) { 16193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung handleTouchEvent(ev); 16293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 16393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 16493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung /** 16593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * Handles the touch event and determines whether to show the fast scroller (or updates it if 16693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * it is already showing). 16793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */ 16893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private boolean handleTouchEvent(MotionEvent ev) { 16993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung ViewConfiguration config = ViewConfiguration.get(getContext()); 17093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 17193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int action = ev.getAction(); 17293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int x = (int) ev.getX(); 17393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int y = (int) ev.getY(); 17493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung switch (action) { 17593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung case MotionEvent.ACTION_DOWN: 17693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung // Keep track of the down positions 17793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mDownX = mLastX = x; 17893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mDownY = mLastY = y; 17993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung stopScroll(); 18093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung break; 18193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung case MotionEvent.ACTION_MOVE: 18293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung // Check if we are scrolling 18393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung boolean isRtl = (getResources().getConfiguration().getLayoutDirection() == 18493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung LAYOUT_DIRECTION_RTL); 18593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung boolean isInGutter; 18693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung if (isRtl) { 18793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung isInGutter = mDownX < mGutterSize; 18893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } else { 18993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung isInGutter = mDownX >= (getWidth() - mGutterSize); 19093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 19193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung if (!mDraggingFastScroller && isInGutter && 19293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung Math.abs(y - mDownY) > config.getScaledTouchSlop()) { 19393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung getParent().requestDisallowInterceptTouchEvent(true); 19493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mDraggingFastScroller = true; 19593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung animateFastScrollerVisibility(true); 19693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 19793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung if (mDraggingFastScroller) { 19893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mLastX = x; 19993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mLastY = y; 20093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 20193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung // Scroll to the right position, and update the section name 20293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int top = getPaddingTop() + (mFastScrollerBg.getBounds().height() / 2); 20393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int bottom = getHeight() - getPaddingBottom() - 20493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung (mFastScrollerBg.getBounds().height() / 2); 20593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung float boundedY = (float) Math.max(top, Math.min(bottom, y)); 20693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollSectionName = scrollToPositionAtProgress((boundedY - top) / 20793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung (bottom - top)); 20893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung invalidateFastScroller(); 20993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 21093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung break; 21193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung case MotionEvent.ACTION_UP: 21293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung case MotionEvent.ACTION_CANCEL: 21393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mDraggingFastScroller = false; 21493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung animateFastScrollerVisibility(false); 21593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung break; 21693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 21793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung return mDraggingFastScroller; 21893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 21993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 22093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 22193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung /** 22293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * Animates the visibility of the fast scroller popup. 22393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */ 22493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private void animateFastScrollerVisibility(boolean visible) { 22593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung ObjectAnimator anim = ObjectAnimator.ofFloat(this, "fastScrollerAlpha", visible ? 1f : 0f); 22693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung anim.setDuration(visible ? 200 : 150); 22793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung anim.start(); 22893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 22993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 23093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung /** 23193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * Invalidates the fast scroller popup. 23293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */ 23393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private void invalidateFastScroller() { 23493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung invalidate(getWidth() - getPaddingRight() - getScrollBarSize() - 23593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung mFastScrollerBg.getIntrinsicWidth(), 0, getWidth(), getHeight()); 23693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 23793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 23893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung /** 23993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * Maps the progress (from 0..1) to the position that should be visible 24093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */ 24193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung private String scrollToPositionAtProgress(float progress) { 24293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung List<AlphabeticalAppsList.SectionInfo> sections = mApps.getSections(); 24393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung // Get the total number of rows 24493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int rowCount = 0; 24593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung for (AlphabeticalAppsList.SectionInfo info : sections) { 24693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int numRowsInSection = (int) Math.ceil((float) info.numAppsInSection / mNumAppsPerRow); 24793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung rowCount += numRowsInSection; 24893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 24993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 25093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung // Find the index of the first app in that row and scroll to that position 25193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int rowAtProgress = (int) (progress * rowCount); 25293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int appIndex = 0; 25393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung rowCount = 0; 25493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung for (AlphabeticalAppsList.SectionInfo info : sections) { 25593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int numRowsInSection = (int) Math.ceil((float) info.numAppsInSection / mNumAppsPerRow); 25693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung if (rowCount + numRowsInSection > rowAtProgress) { 25793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung appIndex += (rowAtProgress - rowCount) * mNumAppsPerRow; 25893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung break; 25993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 26093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung rowCount += numRowsInSection; 26193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung appIndex += info.numAppsInSection; 26293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 26393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung appIndex = Math.max(0, Math.min(mApps.getAppsWithoutSectionBreaks().size() - 1, appIndex)); 26493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung AppInfo appInfo = mApps.getAppsWithoutSectionBreaks().get(appIndex); 26593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung int sectionedAppIndex = mApps.getApps().indexOf(appInfo); 26693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung scrollToPosition(sectionedAppIndex); 26793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung 26893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung // Returns the section name of the row 26993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung return mApps.getSectionNameForApp(appInfo); 27093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung } 27193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung} 272