FastScroller.java revision 2c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5
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, 6120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell com.android.internal.R.attr.fastScrollThumbDrawable, 6220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell com.android.internal.R.attr.fastScrollTrackDrawable, 6320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell com.android.internal.R.attr.fastScrollPreviewBackgroundLeft, 6420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell com.android.internal.R.attr.fastScrollPreviewBackgroundRight, 6520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell com.android.internal.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 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Resources res = context.getResources(); 23120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell TypedArray ta = context.getTheme().obtainStyledAttributes(ATTRS); 23220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell useThumbDrawable(context, ta.getDrawable(ta.getIndex(THUMB_DRAWABLE))); 23320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mTrackDrawable = ta.getDrawable(ta.getIndex(TRACK_DRAWABLE)); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawableLeft = ta.getDrawable(ta.getIndex(PREVIEW_BACKGROUND_LEFT)); 23620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawableRight = ta.getDrawable(ta.getIndex(PREVIEW_BACKGROUND_RIGHT)); 23720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayPosition = ta.getInt(ta.getIndex(OVERLAY_POSITION), OVERLAY_FLOATING); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScrollCompleted = true; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 241d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy getSectionsFromIndexer(); 2421ffaebc41bfd47472543d1ff86c8412c868fc4c9Amith Yamasani 2431ffaebc41bfd47472543d1ff86c8412c868fc4c9Amith Yamasani mOverlaySize = context.getResources().getDimensionPixelSize( 2441ffaebc41bfd47472543d1ff86c8412c868fc4c9Amith Yamasani com.android.internal.R.dimen.fastscroll_overlay_size); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOverlayPos = new RectF(); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScrollFade = new ScrollFade(); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint = new Paint(); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setAntiAlias(true); 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setTextAlign(Paint.Align.CENTER); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setTextSize(mOverlaySize / 2); 25120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 25220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell ColorStateList textColor = ta.getColorStateList(ta.getIndex(PRIMARY_TEXT_COLOR)); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int textColorNormal = textColor.getDefaultColor(); 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setColor(textColorNormal); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setStyle(Paint.Style.FILL_AND_STROKE); 2569b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora 2579b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora // to show mOverlayDrawable properly 2589b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora if (mList.getWidth() > 0 && mList.getHeight() > 0) { 2599b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora onSizeChanged(mList.getWidth(), mList.getHeight(), 0, 0); 2609b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora } 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_NONE; 26320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell refreshDrawableState(); 26420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 26520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell ta.recycle(); 26620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 26720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell setScrollbarPosition(mList.getVerticalScrollbarPosition()); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void stop() { 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_NONE); 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isVisible() { 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return !(mState == STATE_NONE); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void draw(Canvas canvas) { 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_NONE) { 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No need to draw anything 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int y = mThumbY; 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int viewWidth = mList.getWidth(); 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final FastScroller.ScrollFade scrollFade = mScrollFade; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int alpha = -1; 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_EXIT) { 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = scrollFade.getAlpha(); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alpha < ScrollFade.ALPHA_MAX / 2) { 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbDrawable.setAlpha(alpha * 2); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell int left = 0; 29620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 29720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_DEFAULT: 29820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 29920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX; 30020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 30120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 30220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell left = -mThumbW + (mThumbW * alpha) / ScrollFade.ALPHA_MAX; 30320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 30420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 30520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setBounds(left, 0, left + mThumbW, mThumbH); 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChangedBounds = true; 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mTrackDrawable != null) { 3102c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell final Rect thumbBounds = mThumbDrawable.getBounds(); 3112c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell final int left = thumbBounds.left; 3122c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell final int halfThumbHeight = (thumbBounds.bottom - thumbBounds.top) / 2; 31320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final int trackWidth = mTrackDrawable.getIntrinsicWidth(); 3142c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell final int trackLeft = (left + mThumbW / 2) - trackWidth / 2; 3152c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell mTrackDrawable.setBounds(trackLeft, halfThumbHeight, 3162c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell trackLeft + trackWidth, mList.getHeight() - halfThumbHeight); 31720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mTrackDrawable.draw(canvas); 31820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 31920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.translate(0, y); 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbDrawable.draw(canvas); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.translate(0, -y); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If user is dragging the scroll bar, draw the alphabet overlay 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_DRAGGING && mDrawOverlay) { 32620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mOverlayPosition == OVERLAY_AT_THUMB) { 32720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell int left = 0; 32820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 32920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell default: 33020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_DEFAULT: 33120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 33220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell left = Math.max(0, 33320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.getBounds().left - mThumbW - mOverlaySize); 33420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 33520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 33620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell left = Math.min(mThumbDrawable.getBounds().right + mThumbW, 33720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mList.getWidth() - mOverlaySize); 33820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 33920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 34020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 34120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell int top = Math.max(0, 34220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell Math.min(y + (mThumbH - mOverlaySize) / 2, mList.getHeight() - mOverlaySize)); 34320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 34420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final RectF pos = mOverlayPos; 34520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.left = left; 34620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.right = pos.left + mOverlaySize; 34720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.top = top; 34820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.bottom = pos.top + mOverlaySize; 34920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mOverlayDrawable != null) { 35020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawable.setBounds((int) pos.left, (int) pos.top, 35120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell (int) pos.right, (int) pos.bottom); 35220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 35320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOverlayDrawable.draw(canvas); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Paint paint = mPaint; 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float descent = paint.descent(); 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final RectF rectF = mOverlayPos; 35820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final Rect tmpRect = mTmpRect; 35920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawable.getPadding(tmpRect); 36020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final int hOff = (tmpRect.right - tmpRect.left) / 2; 36120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final int vOff = (tmpRect.bottom - tmpRect.top) / 2; 36220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell canvas.drawText(mSectionText, (int) (rectF.left + rectF.right) / 2 - hOff, 36320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell (int) (rectF.bottom + rectF.top) / 2 + mOverlaySize / 4 - descent - vOff, 36420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell paint); 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mState == STATE_EXIT) { 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alpha == 0) { // Done with exit 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_NONE); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH); 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onSizeChanged(int w, int h, int oldw, int oldh) { 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mThumbDrawable != null) { 37620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 37720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell default: 37820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_DEFAULT: 37920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 38020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setBounds(w - mThumbW, 0, w, mThumbH); 38120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 38220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 38320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setBounds(0, 0, mThumbW, mThumbH); 38420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 38520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mOverlayPosition == OVERLAY_FLOATING) { 38820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final RectF pos = mOverlayPos; 38920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.left = (w - mOverlaySize) / 2; 39020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.right = pos.left + mOverlaySize; 39120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.top = h / 10; // 10% from top 39220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.bottom = pos.top + mOverlaySize; 39320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mOverlayDrawable != null) { 39420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawable.setBounds((int) pos.left, (int) pos.top, 39520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell (int) pos.right, (int) pos.bottom); 39620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3992c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell 4002c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell void onItemCountChanged(int oldCount, int newCount) { 4012c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell if (mAlwaysShow) { 4022c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell mLongList = true; 4032c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell } 4042c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell } 4052c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int totalItemCount) { 4084df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project // Are there enough pages to require fast scroll? Recompute only if total count changes 4094df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (mItemCount != totalItemCount && visibleItemCount > 0) { 4104df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project mItemCount = totalItemCount; 4112c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell mLongList = mAlwaysShow || mItemCount / visibleItemCount >= MIN_PAGES; 4124df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 4134df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (!mLongList) { 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_NONE) { 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_NONE); 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (totalItemCount - visibleItemCount > 0 && mState != STATE_DRAGGING ) { 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbY = ((mList.getHeight() - mThumbH) * firstVisibleItem) 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project / (totalItemCount - visibleItemCount); 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mChangedBounds) { 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetThumbPos(); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChangedBounds = false; 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScrollCompleted = true; 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (firstVisibleItem == mVisibleItem) { 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVisibleItem = firstVisibleItem; 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_DRAGGING) { 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_VISIBLE); 43420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (!mAlwaysShow) { 43520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mHandler.postDelayed(mScrollFade, FADE_TIMEOUT); 43620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 440d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy SectionIndexer getSectionIndexer() { 441d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy return mSectionIndexer; 442d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy } 443d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy 444d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy Object[] getSections() { 445d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy if (mListAdapter == null && mList != null) { 446d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy getSectionsFromIndexer(); 447d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy } 448d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy return mSections; 449d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy } 450d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy 451d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy private void getSectionsFromIndexer() { 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Adapter adapter = mList.getAdapter(); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSectionIndexer = null; 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter instanceof HeaderViewListAdapter) { 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListOffset = ((HeaderViewListAdapter)adapter).getHeadersCount(); 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter(); 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter instanceof ExpandableListConnector) { 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListAdapter expAdapter = ((ExpandableListConnector)adapter).getAdapter(); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (expAdapter instanceof SectionIndexer) { 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSectionIndexer = (SectionIndexer) expAdapter; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListAdapter = (BaseAdapter) adapter; 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSections = mSectionIndexer.getSections(); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter instanceof SectionIndexer) { 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListAdapter = (BaseAdapter) adapter; 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSectionIndexer = (SectionIndexer) adapter; 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSections = mSectionIndexer.getSections(); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListAdapter = (BaseAdapter) adapter; 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSections = new String[] { " " }; 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void scrollTo(float position) { 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mList.getCount(); 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScrollCompleted = false; 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float fThreshold = (1.0f / count) / 8; 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Object[] sections = mSections; 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int sectionIndex; 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sections != null && sections.length > 1) { 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int nSections = sections.length; 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int section = (int) (position * nSections); 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (section >= nSections) { 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project section = nSections - 1; 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int exactSection = section; 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sectionIndex = section; 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = mSectionIndexer.getPositionForSection(section); 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Given the expected section and index, the following code will 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // try to account for missing sections (no names starting with..) 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It will compute the scroll space of surrounding empty sections 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and interpolate the currently visible letter's range across the 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // available space, so that there is always some list movement while 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the user moves the thumb. 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextIndex = count; 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int prevIndex = index; 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int prevSection = section; 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextSection = section + 1; 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Assume the next section is unique 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (section < nSections - 1) { 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextIndex = mSectionIndexer.getPositionForSection(section + 1); 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find the previous index if we're slicing the previous section 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextIndex == index) { 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Non-existent letter 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (section > 0) { 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project section--; 513b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project prevIndex = mSectionIndexer.getPositionForSection(section); 514b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (prevIndex != index) { 515b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project prevSection = section; 516b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project sectionIndex = section; 517b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project break; 518b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } else if (section == 0) { 519b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // When section reaches 0 here, sectionIndex must follow it. 520b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // Assuming mSectionIndexer.getPositionForSection(0) == 0. 521b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project sectionIndex = 0; 522b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project break; 523b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find the next index, in case the assumed next index is not 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // unique. For instance, if there is no P, then request for P's 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // position actually returns Q's. So we need to look ahead to make 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sure that there is really a Q at Q's position. If not, move 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // further down... 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextNextSection = nextSection + 1; 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (nextNextSection < nSections && 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSectionIndexer.getPositionForSection(nextNextSection) == nextIndex) { 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextNextSection++; 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextSection++; 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Compute the beginning and ending scroll range percentage of the 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // currently visible letter. This could be equal to or greater than 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (1 / nSections). 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float fPrev = (float) prevSection / nSections; 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float fNext = (float) nextSection / nSections; 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prevSection == exactSection && position - fPrev < fThreshold) { 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = prevIndex; 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = prevIndex + (int) ((nextIndex - prevIndex) * (position - fPrev) 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project / (fNext - fPrev)); 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't overflow 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index > count - 1) index = count - 1; 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mList instanceof ExpandableListView) { 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListView expList = (ExpandableListView) mList; 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project expList.setSelectionFromTop(expList.getFlatListPosition( 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListView.getPackedPositionForGroup(index + mListOffset)), 0); 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mList instanceof ListView) { 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((ListView)mList).setSelectionFromTop(index + mListOffset, 0); 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.setSelection(index + mListOffset); 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = (int) (position * count); 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mList instanceof ExpandableListView) { 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListView expList = (ExpandableListView) mList; 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project expList.setSelectionFromTop(expList.getFlatListPosition( 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListView.getPackedPositionForGroup(index + mListOffset)), 0); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mList instanceof ListView) { 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((ListView)mList).setSelectionFromTop(index + mListOffset, 0); 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.setSelection(index + mListOffset); 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sectionIndex = -1; 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sectionIndex >= 0) { 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String text = mSectionText = sections[sectionIndex].toString(); 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawOverlay = (text.length() != 1 || text.charAt(0) != ' ') && 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sectionIndex < sections.length; 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawOverlay = false; 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void cancelFling() { 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Cancel the list fling 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MotionEvent cancelFling = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0); 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.onTouchEvent(cancelFling); 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cancelFling.recycle(); 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onInterceptTouchEvent(MotionEvent ev) { 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState > STATE_NONE && ev.getAction() == MotionEvent.ACTION_DOWN) { 59282f3495b146b267f3786997752cef25310176349Romain Guy if (isPointInside(ev.getX(), ev.getY())) { 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_DRAGGING); 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onTouchEvent(MotionEvent me) { 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_NONE) { 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 60482f3495b146b267f3786997752cef25310176349Romain Guy 60582f3495b146b267f3786997752cef25310176349Romain Guy final int action = me.getAction(); 60682f3495b146b267f3786997752cef25310176349Romain Guy 60782f3495b146b267f3786997752cef25310176349Romain Guy if (action == MotionEvent.ACTION_DOWN) { 60882f3495b146b267f3786997752cef25310176349Romain Guy if (isPointInside(me.getX(), me.getY())) { 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_DRAGGING); 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mListAdapter == null && mList != null) { 611d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy getSectionsFromIndexer(); 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 613d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen if (mList != null) { 614d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen mList.requestDisallowInterceptTouchEvent(true); 615d43bd48fe311fa6320e46ca9b9ce25241c476ac6Adam Powell mList.reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 616d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen } 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cancelFling(); 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 621cd3e4ad4fb526c5f36f64f1d1a39a0b3c5e4c462Marco Nelissen } else if (action == MotionEvent.ACTION_UP) { // don't add ACTION_CANCEL here 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_DRAGGING) { 623d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen if (mList != null) { 624d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen // ViewGroup does the right thing already, but there might 625d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen // be other classes that don't properly reset on touch-up, 626d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen // so do this explicitly just in case. 627d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen mList.requestDisallowInterceptTouchEvent(false); 628d43bd48fe311fa6320e46ca9b9ce25241c476ac6Adam Powell mList.reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); 629d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen } 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_VISIBLE); 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Handler handler = mHandler; 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handler.removeCallbacks(mScrollFade); 63320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (!mAlwaysShow) { 63420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell handler.postDelayed(mScrollFade, 1000); 63520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 63620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 63720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mList.invalidate(); 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 64082f3495b146b267f3786997752cef25310176349Romain Guy } else if (action == MotionEvent.ACTION_MOVE) { 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_DRAGGING) { 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int viewHeight = mList.getHeight(); 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Jitter 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newThumbY = (int) me.getY() - mThumbH + 10; 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newThumbY < 0) { 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newThumbY = 0; 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (newThumbY + mThumbH > viewHeight) { 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newThumbY = viewHeight - mThumbH; 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Math.abs(mThumbY - newThumbY) < 2) { 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbY = newThumbY; 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the previous scrollTo is still pending 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mScrollCompleted) { 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollTo((float) mThumbY / (viewHeight - mThumbH)); 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 663d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy 66482f3495b146b267f3786997752cef25310176349Romain Guy boolean isPointInside(float x, float y) { 66520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell boolean inTrack = false; 66620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 66720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell default: 66820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_DEFAULT: 66920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 67020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell inTrack = x > mList.getWidth() - mThumbW; 67120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 67220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 67320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell inTrack = x < mThumbW; 67420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 67520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 67620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 67720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell // Allow taps in the track to start moving. 67820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell return inTrack && (mTrackDrawable != null || y >= mThumbY && y <= mThumbY + mThumbH); 67982f3495b146b267f3786997752cef25310176349Romain Guy } 68082f3495b146b267f3786997752cef25310176349Romain Guy 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public class ScrollFade implements Runnable { 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mStartTime; 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mFadeDuration; 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int ALPHA_MAX = 208; 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final long FADE_DURATION = 200; 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void startFade() { 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFadeDuration = FADE_DURATION; 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStartTime = SystemClock.uptimeMillis(); 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_EXIT); 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int getAlpha() { 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getState() != STATE_EXIT) { 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ALPHA_MAX; 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int alpha; 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = SystemClock.uptimeMillis(); 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (now > mStartTime + mFadeDuration) { 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = 0; 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = (int) (ALPHA_MAX - ((now - mStartTime) * ALPHA_MAX) / mFadeDuration); 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return alpha; 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getState() != STATE_EXIT) { 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startFade(); 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getAlpha() > 0) { 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.invalidate(); 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_NONE); 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 722