FastScroller.java revision 128b6ba93d0549fd2beff4482678e1229dc1cf3d
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.ColorStateList; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint; 2520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powellimport android.graphics.Rect; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.RectF; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable; 2820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powellimport android.graphics.drawable.NinePatchDrawable; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MotionEvent; 3220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powellimport android.view.View; 33d43bd48fe311fa6320e46ca9b9ce25241c476ac6Adam Powellimport android.widget.AbsListView.OnScrollListener; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Helper class for AbsListView to draw and control the Fast Scroll thumb 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass FastScroller { 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Minimum number of pages to justify showing a fast scroll thumb 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static int MIN_PAGES = 4; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Scroll thumb not showing 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int STATE_NONE = 0; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Not implemented yet - fade-in transition 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int STATE_ENTER = 1; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Scroll thumb visible and moving along with the scrollbar 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int STATE_VISIBLE = 2; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Scroll thumb being dragged by user 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int STATE_DRAGGING = 3; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Scroll thumb fading out due to inactivity timeout 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int STATE_EXIT = 4; 5220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 5320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int[] PRESSED_STATES = new int[] { 5420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell android.R.attr.state_pressed 5520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell }; 5620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 5720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int[] DEFAULT_STATES = new int[0]; 5820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 5920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int[] ATTRS = new int[] { 6020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell android.R.attr.textColorPrimary, 61128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell android.R.attr.fastScrollThumbDrawable, 62128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell android.R.attr.fastScrollTrackDrawable, 63128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell android.R.attr.fastScrollPreviewBackgroundLeft, 64128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell android.R.attr.fastScrollPreviewBackgroundRight, 65128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell android.R.attr.fastScrollOverlayPosition 6620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell }; 6720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 6820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int PRIMARY_TEXT_COLOR = 0; 6920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int THUMB_DRAWABLE = 1; 7020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int TRACK_DRAWABLE = 2; 7120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int PREVIEW_BACKGROUND_LEFT = 3; 7220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int PREVIEW_BACKGROUND_RIGHT = 4; 7320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int OVERLAY_POSITION = 5; 7420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 7520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int OVERLAY_FLOATING = 0; 7620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int OVERLAY_AT_THUMB = 1; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mThumbDrawable; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mOverlayDrawable; 8020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private Drawable mTrackDrawable; 8120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 8220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private Drawable mOverlayDrawableLeft; 8320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private Drawable mOverlayDrawableRight; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mThumbH; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mThumbW; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mThumbY; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private RectF mOverlayPos; 901ffaebc41bfd47472543d1ff86c8412c868fc4c9Amith Yamasani private int mOverlaySize; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AbsListView mList; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mScrollCompleted; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mVisibleItem; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Paint mPaint; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mListOffset; 974df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project private int mItemCount = -1; 984df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project private boolean mLongList; 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Object [] mSections; 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mSectionText; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mDrawOverlay; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ScrollFade mScrollFade; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mState; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Handler mHandler = new Handler(); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private BaseAdapter mListAdapter; 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SectionIndexer mSectionIndexer; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mChangedBounds; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private int mPosition; 11520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 11620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private boolean mAlwaysShow; 11720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 11820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private int mOverlayPosition; 11920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 12020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int FADE_TIMEOUT = 1500; 12120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 12220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private final Rect mTmpRect = new Rect(); 12320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public FastScroller(Context context, AbsListView listView) { 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList = listView; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project init(context); 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell public void setAlwaysShow(boolean alwaysShow) { 13020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mAlwaysShow = alwaysShow; 13120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (alwaysShow) { 13220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mHandler.removeCallbacks(mScrollFade); 13320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell setState(STATE_VISIBLE); 13420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } else if (mState == STATE_VISIBLE) { 13520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mHandler.postDelayed(mScrollFade, FADE_TIMEOUT); 13620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 13720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 13820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 13920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell public boolean isAlwaysShowEnabled() { 14020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell return mAlwaysShow; 14120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 14220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 14320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private void refreshDrawableState() { 14420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell int[] state = mState == STATE_DRAGGING ? PRESSED_STATES : DEFAULT_STATES; 14520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 14620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mThumbDrawable != null && mThumbDrawable.isStateful()) { 14720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setState(state); 14820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 14920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mTrackDrawable != null && mTrackDrawable.isStateful()) { 15020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mTrackDrawable.setState(state); 15120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 15220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 15320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 15420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell public void setScrollbarPosition(int position) { 15520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mPosition = position; 15620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (position) { 15720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell default: 15820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_DEFAULT: 15920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 16020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawable = mOverlayDrawableRight; 16120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 16220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 16320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawable = mOverlayDrawableLeft; 16420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 16520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 16620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 16720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 16820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell public int getWidth() { 16920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell return mThumbW; 17020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 17120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setState(int state) { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (state) { 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STATE_NONE: 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeCallbacks(mScrollFade); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.invalidate(); 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STATE_VISIBLE: 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_VISIBLE) { // Optimization 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetThumbPos(); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fall through 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STATE_DRAGGING: 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeCallbacks(mScrollFade); 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STATE_EXIT: 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int viewWidth = mList.getWidth(); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.invalidate(viewWidth - mThumbW, mThumbY, viewWidth, mThumbY + mThumbH); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = state; 19220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell refreshDrawableState(); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getState() { 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mState; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void resetThumbPos() { 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int viewWidth = mList.getWidth(); 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Bounds are always top right. Y coordinate get's translated during draw 20220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 20320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_DEFAULT: 20420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 20520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setBounds(viewWidth - mThumbW, 0, viewWidth, mThumbH); 20620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 20720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 20820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setBounds(0, 0, mThumbW, mThumbH); 20920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 21020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbDrawable.setAlpha(ScrollFade.ALPHA_MAX); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 214a5e441525660765e0913140daff4d12a0d94e88cMitsuru Oshima private void useThumbDrawable(Context context, Drawable drawable) { 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbDrawable = drawable; 21620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (drawable instanceof NinePatchDrawable) { 21720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbW = context.getResources().getDimensionPixelSize( 21820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell com.android.internal.R.dimen.fastscroll_thumb_width); 21920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbH = context.getResources().getDimensionPixelSize( 22020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell com.android.internal.R.dimen.fastscroll_thumb_height); 22120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } else { 22220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbW = drawable.getIntrinsicWidth(); 22320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbH = drawable.getIntrinsicHeight(); 22420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChangedBounds = true; 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void init(Context context) { 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get both the scrollbar states drawables 23020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell TypedArray ta = context.getTheme().obtainStyledAttributes(ATTRS); 231128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell useThumbDrawable(context, ta.getDrawable(THUMB_DRAWABLE)); 232128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell mTrackDrawable = ta.getDrawable(TRACK_DRAWABLE); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 234128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell mOverlayDrawableLeft = ta.getDrawable(PREVIEW_BACKGROUND_LEFT); 235128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell mOverlayDrawableRight = ta.getDrawable(PREVIEW_BACKGROUND_RIGHT); 236128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell mOverlayPosition = ta.getInt(OVERLAY_POSITION, OVERLAY_FLOATING); 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScrollCompleted = true; 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 240d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy getSectionsFromIndexer(); 2411ffaebc41bfd47472543d1ff86c8412c868fc4c9Amith Yamasani 2421ffaebc41bfd47472543d1ff86c8412c868fc4c9Amith Yamasani mOverlaySize = context.getResources().getDimensionPixelSize( 2431ffaebc41bfd47472543d1ff86c8412c868fc4c9Amith Yamasani com.android.internal.R.dimen.fastscroll_overlay_size); 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOverlayPos = new RectF(); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScrollFade = new ScrollFade(); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint = new Paint(); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setAntiAlias(true); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setTextAlign(Paint.Align.CENTER); 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setTextSize(mOverlaySize / 2); 25020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 251128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell ColorStateList textColor = ta.getColorStateList(PRIMARY_TEXT_COLOR); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int textColorNormal = textColor.getDefaultColor(); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setColor(textColorNormal); 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setStyle(Paint.Style.FILL_AND_STROKE); 2559b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora 2569b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora // to show mOverlayDrawable properly 2579b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora if (mList.getWidth() > 0 && mList.getHeight() > 0) { 2589b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora onSizeChanged(mList.getWidth(), mList.getHeight(), 0, 0); 2599b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora } 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_NONE; 26220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell refreshDrawableState(); 26320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 26420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell ta.recycle(); 26520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 26620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell setScrollbarPosition(mList.getVerticalScrollbarPosition()); 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void stop() { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_NONE); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isVisible() { 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return !(mState == STATE_NONE); 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void draw(Canvas canvas) { 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_NONE) { 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No need to draw anything 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int y = mThumbY; 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int viewWidth = mList.getWidth(); 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final FastScroller.ScrollFade scrollFade = mScrollFade; 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int alpha = -1; 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_EXIT) { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = scrollFade.getAlpha(); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alpha < ScrollFade.ALPHA_MAX / 2) { 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbDrawable.setAlpha(alpha * 2); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell int left = 0; 29520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 29620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_DEFAULT: 29720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 29820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX; 29920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 30020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 30120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell left = -mThumbW + (mThumbW * alpha) / ScrollFade.ALPHA_MAX; 30220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 30320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 30420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setBounds(left, 0, left + mThumbW, mThumbH); 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChangedBounds = true; 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mTrackDrawable != null) { 3092c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell final Rect thumbBounds = mThumbDrawable.getBounds(); 3102c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell final int left = thumbBounds.left; 3112c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell final int halfThumbHeight = (thumbBounds.bottom - thumbBounds.top) / 2; 31220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final int trackWidth = mTrackDrawable.getIntrinsicWidth(); 3132c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell final int trackLeft = (left + mThumbW / 2) - trackWidth / 2; 3142c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell mTrackDrawable.setBounds(trackLeft, halfThumbHeight, 3152c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell trackLeft + trackWidth, mList.getHeight() - halfThumbHeight); 31620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mTrackDrawable.draw(canvas); 31720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 31820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.translate(0, y); 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbDrawable.draw(canvas); 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.translate(0, -y); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If user is dragging the scroll bar, draw the alphabet overlay 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_DRAGGING && mDrawOverlay) { 32520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mOverlayPosition == OVERLAY_AT_THUMB) { 32620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell int left = 0; 32720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 32820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell default: 32920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_DEFAULT: 33020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 33120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell left = Math.max(0, 33220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.getBounds().left - mThumbW - mOverlaySize); 33320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 33420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 33520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell left = Math.min(mThumbDrawable.getBounds().right + mThumbW, 33620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mList.getWidth() - mOverlaySize); 33720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 33820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 33920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 34020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell int top = Math.max(0, 34120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell Math.min(y + (mThumbH - mOverlaySize) / 2, mList.getHeight() - mOverlaySize)); 34220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 34320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final RectF pos = mOverlayPos; 34420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.left = left; 34520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.right = pos.left + mOverlaySize; 34620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.top = top; 34720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.bottom = pos.top + mOverlaySize; 34820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mOverlayDrawable != null) { 34920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawable.setBounds((int) pos.left, (int) pos.top, 35020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell (int) pos.right, (int) pos.bottom); 35120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 35220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOverlayDrawable.draw(canvas); 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Paint paint = mPaint; 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float descent = paint.descent(); 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final RectF rectF = mOverlayPos; 35720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final Rect tmpRect = mTmpRect; 35820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawable.getPadding(tmpRect); 35920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final int hOff = (tmpRect.right - tmpRect.left) / 2; 36020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final int vOff = (tmpRect.bottom - tmpRect.top) / 2; 36120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell canvas.drawText(mSectionText, (int) (rectF.left + rectF.right) / 2 - hOff, 36220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell (int) (rectF.bottom + rectF.top) / 2 + mOverlaySize / 4 - descent - vOff, 36320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell paint); 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mState == STATE_EXIT) { 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alpha == 0) { // Done with exit 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_NONE); 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onSizeChanged(int w, int h, int oldw, int oldh) { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mThumbDrawable != null) { 37520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 37620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell default: 37720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_DEFAULT: 37820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 37920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setBounds(w - mThumbW, 0, w, mThumbH); 38020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 38120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 38220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setBounds(0, 0, mThumbW, mThumbH); 38320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 38420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mOverlayPosition == OVERLAY_FLOATING) { 38720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final RectF pos = mOverlayPos; 38820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.left = (w - mOverlaySize) / 2; 38920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.right = pos.left + mOverlaySize; 39020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.top = h / 10; // 10% from top 39120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.bottom = pos.top + mOverlaySize; 39220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mOverlayDrawable != null) { 39320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawable.setBounds((int) pos.left, (int) pos.top, 39420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell (int) pos.right, (int) pos.bottom); 39520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3982c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell 3992c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell void onItemCountChanged(int oldCount, int newCount) { 4002c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell if (mAlwaysShow) { 4012c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell mLongList = true; 4022c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell } 4032c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell } 4042c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int totalItemCount) { 4074df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project // Are there enough pages to require fast scroll? Recompute only if total count changes 4084df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (mItemCount != totalItemCount && visibleItemCount > 0) { 4094df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project mItemCount = totalItemCount; 4102c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell mLongList = mAlwaysShow || mItemCount / visibleItemCount >= MIN_PAGES; 4114df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 4124df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (!mLongList) { 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_NONE) { 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_NONE); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (totalItemCount - visibleItemCount > 0 && mState != STATE_DRAGGING ) { 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbY = ((mList.getHeight() - mThumbH) * firstVisibleItem) 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project / (totalItemCount - visibleItemCount); 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mChangedBounds) { 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetThumbPos(); 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChangedBounds = false; 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScrollCompleted = true; 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (firstVisibleItem == mVisibleItem) { 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVisibleItem = firstVisibleItem; 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_DRAGGING) { 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_VISIBLE); 43320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (!mAlwaysShow) { 43420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mHandler.postDelayed(mScrollFade, FADE_TIMEOUT); 43520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 439d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy SectionIndexer getSectionIndexer() { 440d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy return mSectionIndexer; 441d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy } 442d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy 443d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy Object[] getSections() { 444d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy if (mListAdapter == null && mList != null) { 445d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy getSectionsFromIndexer(); 446d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy } 447d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy return mSections; 448d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy } 449d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy 450d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy private void getSectionsFromIndexer() { 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Adapter adapter = mList.getAdapter(); 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSectionIndexer = null; 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter instanceof HeaderViewListAdapter) { 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListOffset = ((HeaderViewListAdapter)adapter).getHeadersCount(); 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter(); 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter instanceof ExpandableListConnector) { 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListAdapter expAdapter = ((ExpandableListConnector)adapter).getAdapter(); 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (expAdapter instanceof SectionIndexer) { 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSectionIndexer = (SectionIndexer) expAdapter; 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListAdapter = (BaseAdapter) adapter; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSections = mSectionIndexer.getSections(); 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter instanceof SectionIndexer) { 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListAdapter = (BaseAdapter) adapter; 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSectionIndexer = (SectionIndexer) adapter; 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSections = mSectionIndexer.getSections(); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListAdapter = (BaseAdapter) adapter; 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSections = new String[] { " " }; 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void scrollTo(float position) { 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mList.getCount(); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScrollCompleted = false; 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float fThreshold = (1.0f / count) / 8; 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Object[] sections = mSections; 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int sectionIndex; 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sections != null && sections.length > 1) { 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int nSections = sections.length; 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int section = (int) (position * nSections); 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (section >= nSections) { 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project section = nSections - 1; 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int exactSection = section; 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sectionIndex = section; 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = mSectionIndexer.getPositionForSection(section); 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Given the expected section and index, the following code will 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // try to account for missing sections (no names starting with..) 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It will compute the scroll space of surrounding empty sections 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and interpolate the currently visible letter's range across the 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // available space, so that there is always some list movement while 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the user moves the thumb. 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextIndex = count; 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int prevIndex = index; 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int prevSection = section; 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextSection = section + 1; 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Assume the next section is unique 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (section < nSections - 1) { 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextIndex = mSectionIndexer.getPositionForSection(section + 1); 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find the previous index if we're slicing the previous section 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextIndex == index) { 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Non-existent letter 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (section > 0) { 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project section--; 512b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project prevIndex = mSectionIndexer.getPositionForSection(section); 513b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (prevIndex != index) { 514b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project prevSection = section; 515b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project sectionIndex = section; 516b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project break; 517b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } else if (section == 0) { 518b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // When section reaches 0 here, sectionIndex must follow it. 519b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // Assuming mSectionIndexer.getPositionForSection(0) == 0. 520b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project sectionIndex = 0; 521b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project break; 522b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find the next index, in case the assumed next index is not 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // unique. For instance, if there is no P, then request for P's 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // position actually returns Q's. So we need to look ahead to make 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sure that there is really a Q at Q's position. If not, move 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // further down... 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextNextSection = nextSection + 1; 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (nextNextSection < nSections && 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSectionIndexer.getPositionForSection(nextNextSection) == nextIndex) { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextNextSection++; 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextSection++; 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Compute the beginning and ending scroll range percentage of the 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // currently visible letter. This could be equal to or greater than 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (1 / nSections). 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float fPrev = (float) prevSection / nSections; 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float fNext = (float) nextSection / nSections; 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prevSection == exactSection && position - fPrev < fThreshold) { 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = prevIndex; 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = prevIndex + (int) ((nextIndex - prevIndex) * (position - fPrev) 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project / (fNext - fPrev)); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't overflow 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index > count - 1) index = count - 1; 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mList instanceof ExpandableListView) { 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListView expList = (ExpandableListView) mList; 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project expList.setSelectionFromTop(expList.getFlatListPosition( 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListView.getPackedPositionForGroup(index + mListOffset)), 0); 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mList instanceof ListView) { 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((ListView)mList).setSelectionFromTop(index + mListOffset, 0); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.setSelection(index + mListOffset); 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = (int) (position * count); 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mList instanceof ExpandableListView) { 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListView expList = (ExpandableListView) mList; 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project expList.setSelectionFromTop(expList.getFlatListPosition( 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListView.getPackedPositionForGroup(index + mListOffset)), 0); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mList instanceof ListView) { 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((ListView)mList).setSelectionFromTop(index + mListOffset, 0); 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.setSelection(index + mListOffset); 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sectionIndex = -1; 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sectionIndex >= 0) { 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String text = mSectionText = sections[sectionIndex].toString(); 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawOverlay = (text.length() != 1 || text.charAt(0) != ' ') && 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sectionIndex < sections.length; 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawOverlay = false; 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void cancelFling() { 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Cancel the list fling 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MotionEvent cancelFling = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0); 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.onTouchEvent(cancelFling); 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cancelFling.recycle(); 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onInterceptTouchEvent(MotionEvent ev) { 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState > STATE_NONE && ev.getAction() == MotionEvent.ACTION_DOWN) { 59182f3495b146b267f3786997752cef25310176349Romain Guy if (isPointInside(ev.getX(), ev.getY())) { 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_DRAGGING); 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onTouchEvent(MotionEvent me) { 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_NONE) { 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 60382f3495b146b267f3786997752cef25310176349Romain Guy 60482f3495b146b267f3786997752cef25310176349Romain Guy final int action = me.getAction(); 60582f3495b146b267f3786997752cef25310176349Romain Guy 60682f3495b146b267f3786997752cef25310176349Romain Guy if (action == MotionEvent.ACTION_DOWN) { 60782f3495b146b267f3786997752cef25310176349Romain Guy if (isPointInside(me.getX(), me.getY())) { 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_DRAGGING); 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mListAdapter == null && mList != null) { 610d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy getSectionsFromIndexer(); 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 612d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen if (mList != null) { 613d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen mList.requestDisallowInterceptTouchEvent(true); 614d43bd48fe311fa6320e46ca9b9ce25241c476ac6Adam Powell mList.reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 615d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen } 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cancelFling(); 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 620cd3e4ad4fb526c5f36f64f1d1a39a0b3c5e4c462Marco Nelissen } else if (action == MotionEvent.ACTION_UP) { // don't add ACTION_CANCEL here 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_DRAGGING) { 622d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen if (mList != null) { 623d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen // ViewGroup does the right thing already, but there might 624d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen // be other classes that don't properly reset on touch-up, 625d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen // so do this explicitly just in case. 626d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen mList.requestDisallowInterceptTouchEvent(false); 627d43bd48fe311fa6320e46ca9b9ce25241c476ac6Adam Powell mList.reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); 628d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen } 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_VISIBLE); 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Handler handler = mHandler; 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handler.removeCallbacks(mScrollFade); 63220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (!mAlwaysShow) { 63320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell handler.postDelayed(mScrollFade, 1000); 63420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 63520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 63620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mList.invalidate(); 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 63982f3495b146b267f3786997752cef25310176349Romain Guy } else if (action == MotionEvent.ACTION_MOVE) { 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_DRAGGING) { 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int viewHeight = mList.getHeight(); 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Jitter 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newThumbY = (int) me.getY() - mThumbH + 10; 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newThumbY < 0) { 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newThumbY = 0; 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (newThumbY + mThumbH > viewHeight) { 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newThumbY = viewHeight - mThumbH; 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Math.abs(mThumbY - newThumbY) < 2) { 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbY = newThumbY; 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the previous scrollTo is still pending 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mScrollCompleted) { 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollTo((float) mThumbY / (viewHeight - mThumbH)); 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 662d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy 66382f3495b146b267f3786997752cef25310176349Romain Guy boolean isPointInside(float x, float y) { 66420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell boolean inTrack = false; 66520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 66620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell default: 66720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_DEFAULT: 66820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 66920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell inTrack = x > mList.getWidth() - mThumbW; 67020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 67120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 67220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell inTrack = x < mThumbW; 67320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 67420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 67520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 67620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell // Allow taps in the track to start moving. 67720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell return inTrack && (mTrackDrawable != null || y >= mThumbY && y <= mThumbY + mThumbH); 67882f3495b146b267f3786997752cef25310176349Romain Guy } 67982f3495b146b267f3786997752cef25310176349Romain Guy 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public class ScrollFade implements Runnable { 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mStartTime; 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mFadeDuration; 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int ALPHA_MAX = 208; 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final long FADE_DURATION = 200; 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void startFade() { 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFadeDuration = FADE_DURATION; 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStartTime = SystemClock.uptimeMillis(); 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_EXIT); 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int getAlpha() { 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getState() != STATE_EXIT) { 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ALPHA_MAX; 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int alpha; 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = SystemClock.uptimeMillis(); 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (now > mStartTime + mFadeDuration) { 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = 0; 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = (int) (ALPHA_MAX - ((now - mStartTime) * ALPHA_MAX) / mFadeDuration); 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return alpha; 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getState() != STATE_EXIT) { 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startFade(); 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getAlpha() > 0) { 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.invalidate(); 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_NONE); 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 721