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.TypedArray; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint; 2420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powellimport android.graphics.Rect; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.RectF; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable; 2720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powellimport android.graphics.drawable.NinePatchDrawable; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MotionEvent; 3120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powellimport android.view.View; 32af5280cc71e155758c2f6625eb999cabb37e937fAdam Powellimport android.view.ViewConfiguration; 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 { 39af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell private static final String TAG = "FastScroller"; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Minimum number of pages to justify showing a fast scroll thumb 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static int MIN_PAGES = 4; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Scroll thumb not showing 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int STATE_NONE = 0; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Not implemented yet - fade-in transition 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int STATE_ENTER = 1; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Scroll thumb visible and moving along with the scrollbar 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int STATE_VISIBLE = 2; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Scroll thumb being dragged by user 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int STATE_DRAGGING = 3; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Scroll thumb fading out due to inactivity timeout 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int STATE_EXIT = 4; 5320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 5420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int[] PRESSED_STATES = new int[] { 5520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell android.R.attr.state_pressed 5620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell }; 5720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 5820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int[] DEFAULT_STATES = new int[0]; 5920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 6020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int[] ATTRS = new int[] { 61b2e551711aa93a3d296ced6368e895743d43da80Adam Powell android.R.attr.fastScrollTextColor, 62128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell android.R.attr.fastScrollThumbDrawable, 63128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell android.R.attr.fastScrollTrackDrawable, 64128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell android.R.attr.fastScrollPreviewBackgroundLeft, 65128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell android.R.attr.fastScrollPreviewBackgroundRight, 66128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell android.R.attr.fastScrollOverlayPosition 6720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell }; 6820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 69b2e551711aa93a3d296ced6368e895743d43da80Adam Powell private static final int TEXT_COLOR = 0; 7020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int THUMB_DRAWABLE = 1; 7120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int TRACK_DRAWABLE = 2; 7220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int PREVIEW_BACKGROUND_LEFT = 3; 7320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int PREVIEW_BACKGROUND_RIGHT = 4; 7420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int OVERLAY_POSITION = 5; 7520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 7620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int OVERLAY_FLOATING = 0; 7720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int OVERLAY_AT_THUMB = 1; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mThumbDrawable; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mOverlayDrawable; 8120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private Drawable mTrackDrawable; 8220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 8320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private Drawable mOverlayDrawableLeft; 8420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private Drawable mOverlayDrawableRight; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 86af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell int mThumbH; 87af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell int mThumbW; 88af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell int mThumbY; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private RectF mOverlayPos; 911ffaebc41bfd47472543d1ff86c8412c868fc4c9Amith Yamasani private int mOverlaySize; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 93af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell AbsListView mList; 94af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell boolean mScrollCompleted; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mVisibleItem; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Paint mPaint; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mListOffset; 984df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project private int mItemCount = -1; 994df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project private boolean mLongList; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Object [] mSections; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mSectionText; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mDrawOverlay; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ScrollFade mScrollFade; 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mState; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Handler mHandler = new Handler(); 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 110af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell BaseAdapter mListAdapter; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SectionIndexer mSectionIndexer; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mChangedBounds; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private int mPosition; 11620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 11720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private boolean mAlwaysShow; 11820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 11920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private int mOverlayPosition; 12020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 121568ccd88d7efd33da0c535e07b7ea7cf476be22aAdam Powell private boolean mMatchDragPosition; 122568ccd88d7efd33da0c535e07b7ea7cf476be22aAdam Powell 123af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell float mInitialTouchY; 124af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell boolean mPendingDrag; 125af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell private int mScaledTouchSlop; 126af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell 12720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private static final int FADE_TIMEOUT = 1500; 128af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell private static final int PENDING_DRAG_DELAY = 180; 12920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 13020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private final Rect mTmpRect = new Rect(); 13120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 132af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell private final Runnable mDeferStartDrag = new Runnable() { 133af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell public void run() { 134af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell if (mList.mIsAttached) { 135af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell beginDrag(); 136af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell 137af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell final int viewHeight = mList.getHeight(); 138af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell // Jitter 139af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell int newThumbY = (int) mInitialTouchY - mThumbH + 10; 140af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell if (newThumbY < 0) { 141af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell newThumbY = 0; 142af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } else if (newThumbY + mThumbH > viewHeight) { 143af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell newThumbY = viewHeight - mThumbH; 144af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 145af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mThumbY = newThumbY; 146af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell scrollTo((float) mThumbY / (viewHeight - mThumbH)); 147af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 148af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell 149af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mPendingDrag = false; 150af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 151af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell }; 152af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public FastScroller(Context context, AbsListView listView) { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList = listView; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project init(context); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell public void setAlwaysShow(boolean alwaysShow) { 15920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mAlwaysShow = alwaysShow; 16020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (alwaysShow) { 16120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mHandler.removeCallbacks(mScrollFade); 16220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell setState(STATE_VISIBLE); 16320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } else if (mState == STATE_VISIBLE) { 16420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mHandler.postDelayed(mScrollFade, FADE_TIMEOUT); 16520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 16620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 16720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 16820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell public boolean isAlwaysShowEnabled() { 16920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell return mAlwaysShow; 17020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 17120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 17220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell private void refreshDrawableState() { 17320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell int[] state = mState == STATE_DRAGGING ? PRESSED_STATES : DEFAULT_STATES; 17420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 17520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mThumbDrawable != null && mThumbDrawable.isStateful()) { 17620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setState(state); 17720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 17820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mTrackDrawable != null && mTrackDrawable.isStateful()) { 17920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mTrackDrawable.setState(state); 18020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 18120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 18220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 18320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell public void setScrollbarPosition(int position) { 184c23ee46c8fac06b1982d115368f772fea399a4e0Fabrice Di Meglio if (position == View.SCROLLBAR_POSITION_DEFAULT) { 185c23ee46c8fac06b1982d115368f772fea399a4e0Fabrice Di Meglio position = mList.isLayoutRtl() ? 186c23ee46c8fac06b1982d115368f772fea399a4e0Fabrice Di Meglio View.SCROLLBAR_POSITION_LEFT : View.SCROLLBAR_POSITION_RIGHT; 187c23ee46c8fac06b1982d115368f772fea399a4e0Fabrice Di Meglio } 18820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mPosition = position; 18920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (position) { 19020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell default: 19120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 19220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawable = mOverlayDrawableRight; 19320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 19420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 19520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawable = mOverlayDrawableLeft; 19620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 19720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 19820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 19920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 20020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell public int getWidth() { 20120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell return mThumbW; 20220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 20320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setState(int state) { 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (state) { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STATE_NONE: 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeCallbacks(mScrollFade); 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.invalidate(); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STATE_VISIBLE: 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_VISIBLE) { // Optimization 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetThumbPos(); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fall through 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STATE_DRAGGING: 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeCallbacks(mScrollFade); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case STATE_EXIT: 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int viewWidth = mList.getWidth(); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.invalidate(viewWidth - mThumbW, mThumbY, viewWidth, mThumbY + mThumbH); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = state; 22420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell refreshDrawableState(); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getState() { 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mState; 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void resetThumbPos() { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int viewWidth = mList.getWidth(); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Bounds are always top right. Y coordinate get's translated during draw 23420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 23520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 23620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setBounds(viewWidth - mThumbW, 0, viewWidth, mThumbH); 23720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 23820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 23920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setBounds(0, 0, mThumbW, mThumbH); 24020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 24120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbDrawable.setAlpha(ScrollFade.ALPHA_MAX); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 245a5e441525660765e0913140daff4d12a0d94e88cMitsuru Oshima private void useThumbDrawable(Context context, Drawable drawable) { 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbDrawable = drawable; 24720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (drawable instanceof NinePatchDrawable) { 24820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbW = context.getResources().getDimensionPixelSize( 24920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell com.android.internal.R.dimen.fastscroll_thumb_width); 25020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbH = context.getResources().getDimensionPixelSize( 25120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell com.android.internal.R.dimen.fastscroll_thumb_height); 25220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } else { 25320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbW = drawable.getIntrinsicWidth(); 25420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbH = drawable.getIntrinsicHeight(); 25520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChangedBounds = true; 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void init(Context context) { 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get both the scrollbar states drawables 26120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell TypedArray ta = context.getTheme().obtainStyledAttributes(ATTRS); 262128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell useThumbDrawable(context, ta.getDrawable(THUMB_DRAWABLE)); 263128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell mTrackDrawable = ta.getDrawable(TRACK_DRAWABLE); 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 265128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell mOverlayDrawableLeft = ta.getDrawable(PREVIEW_BACKGROUND_LEFT); 266128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell mOverlayDrawableRight = ta.getDrawable(PREVIEW_BACKGROUND_RIGHT); 267128b6ba93d0549fd2beff4482678e1229dc1cf3dAdam Powell mOverlayPosition = ta.getInt(OVERLAY_POSITION, OVERLAY_FLOATING); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScrollCompleted = true; 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 271d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy getSectionsFromIndexer(); 2721ffaebc41bfd47472543d1ff86c8412c868fc4c9Amith Yamasani 2731ffaebc41bfd47472543d1ff86c8412c868fc4c9Amith Yamasani mOverlaySize = context.getResources().getDimensionPixelSize( 2741ffaebc41bfd47472543d1ff86c8412c868fc4c9Amith Yamasani com.android.internal.R.dimen.fastscroll_overlay_size); 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOverlayPos = new RectF(); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScrollFade = new ScrollFade(); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint = new Paint(); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setAntiAlias(true); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setTextAlign(Paint.Align.CENTER); 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setTextSize(mOverlaySize / 2); 28120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 282b2e551711aa93a3d296ced6368e895743d43da80Adam Powell ColorStateList textColor = ta.getColorStateList(TEXT_COLOR); 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int textColorNormal = textColor.getDefaultColor(); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setColor(textColorNormal); 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint.setStyle(Paint.Style.FILL_AND_STROKE); 2869b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora 2879b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora // to show mOverlayDrawable properly 2889b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora if (mList.getWidth() > 0 && mList.getHeight() > 0) { 2899b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora onSizeChanged(mList.getWidth(), mList.getHeight(), 0, 0); 2909b38c6097e8d866fad1a12c1aba1a9c36e1725d7NoraBora } 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_NONE; 29320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell refreshDrawableState(); 29420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 29520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell ta.recycle(); 29620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 297af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 298af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell 299568ccd88d7efd33da0c535e07b7ea7cf476be22aAdam Powell mMatchDragPosition = context.getApplicationInfo().targetSdkVersion >= 300568ccd88d7efd33da0c535e07b7ea7cf476be22aAdam Powell android.os.Build.VERSION_CODES.HONEYCOMB; 301568ccd88d7efd33da0c535e07b7ea7cf476be22aAdam Powell 30220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell setScrollbarPosition(mList.getVerticalScrollbarPosition()); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void stop() { 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_NONE); 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isVisible() { 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return !(mState == STATE_NONE); 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void draw(Canvas canvas) { 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_NONE) { 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No need to draw anything 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int y = mThumbY; 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int viewWidth = mList.getWidth(); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final FastScroller.ScrollFade scrollFade = mScrollFade; 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int alpha = -1; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_EXIT) { 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = scrollFade.getAlpha(); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alpha < ScrollFade.ALPHA_MAX / 2) { 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbDrawable.setAlpha(alpha * 2); 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell int left = 0; 33120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 33220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 33320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX; 33420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 33520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 33620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell left = -mThumbW + (mThumbW * alpha) / ScrollFade.ALPHA_MAX; 33720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 33820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 33920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setBounds(left, 0, left + mThumbW, mThumbH); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChangedBounds = true; 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mTrackDrawable != null) { 3442c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell final Rect thumbBounds = mThumbDrawable.getBounds(); 3452c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell final int left = thumbBounds.left; 3462c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell final int halfThumbHeight = (thumbBounds.bottom - thumbBounds.top) / 2; 34720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final int trackWidth = mTrackDrawable.getIntrinsicWidth(); 3482c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell final int trackLeft = (left + mThumbW / 2) - trackWidth / 2; 3492c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell mTrackDrawable.setBounds(trackLeft, halfThumbHeight, 3502c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell trackLeft + trackWidth, mList.getHeight() - halfThumbHeight); 35120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mTrackDrawable.draw(canvas); 35220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 35320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.translate(0, y); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbDrawable.draw(canvas); 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.translate(0, -y); 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If user is dragging the scroll bar, draw the alphabet overlay 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_DRAGGING && mDrawOverlay) { 36020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mOverlayPosition == OVERLAY_AT_THUMB) { 36120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell int left = 0; 36220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 36320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell default: 36420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 36520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell left = Math.max(0, 36620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.getBounds().left - mThumbW - mOverlaySize); 36720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 36820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 36920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell left = Math.min(mThumbDrawable.getBounds().right + mThumbW, 37020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mList.getWidth() - mOverlaySize); 37120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 37220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 37320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 37420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell int top = Math.max(0, 37520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell Math.min(y + (mThumbH - mOverlaySize) / 2, mList.getHeight() - mOverlaySize)); 37620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 37720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final RectF pos = mOverlayPos; 37820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.left = left; 37920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.right = pos.left + mOverlaySize; 38020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.top = top; 38120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.bottom = pos.top + mOverlaySize; 38220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mOverlayDrawable != null) { 38320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawable.setBounds((int) pos.left, (int) pos.top, 38420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell (int) pos.right, (int) pos.bottom); 38520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 38620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOverlayDrawable.draw(canvas); 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Paint paint = mPaint; 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float descent = paint.descent(); 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final RectF rectF = mOverlayPos; 39120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final Rect tmpRect = mTmpRect; 39220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawable.getPadding(tmpRect); 39320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final int hOff = (tmpRect.right - tmpRect.left) / 2; 39420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final int vOff = (tmpRect.bottom - tmpRect.top) / 2; 39520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell canvas.drawText(mSectionText, (int) (rectF.left + rectF.right) / 2 - hOff, 39620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell (int) (rectF.bottom + rectF.top) / 2 + mOverlaySize / 4 - descent - vOff, 39720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell paint); 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mState == STATE_EXIT) { 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alpha == 0) { // Done with exit 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_NONE); 40135948b7ed502d3f126acc8f2d61e099fa5deb0c7Adam Powell } else if (mTrackDrawable != null) { 40235948b7ed502d3f126acc8f2d61e099fa5deb0c7Adam Powell mList.invalidate(viewWidth - mThumbW, 0, viewWidth, mList.getHeight()); 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 40435948b7ed502d3f126acc8f2d61e099fa5deb0c7Adam Powell mList.invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onSizeChanged(int w, int h, int oldw, int oldh) { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mThumbDrawable != null) { 41120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 41220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell default: 41320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 41420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setBounds(w - mThumbW, 0, w, mThumbH); 41520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 41620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 41720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mThumbDrawable.setBounds(0, 0, mThumbW, mThumbH); 41820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 41920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 42120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mOverlayPosition == OVERLAY_FLOATING) { 42220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell final RectF pos = mOverlayPos; 42320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.left = (w - mOverlaySize) / 2; 42420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.right = pos.left + mOverlaySize; 42520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.top = h / 10; // 10% from top 42620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell pos.bottom = pos.top + mOverlaySize; 42720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (mOverlayDrawable != null) { 42820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mOverlayDrawable.setBounds((int) pos.left, (int) pos.top, 42920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell (int) pos.right, (int) pos.bottom); 43020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4332c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell 4342c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell void onItemCountChanged(int oldCount, int newCount) { 4352c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell if (mAlwaysShow) { 4362c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell mLongList = true; 4372c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell } 4382c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell } 4392c6196aa557e4eaf09d1ec3ad1347742f7f9f7b5Adam Powell 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int totalItemCount) { 4424df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project // Are there enough pages to require fast scroll? Recompute only if total count changes 4434df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (mItemCount != totalItemCount && visibleItemCount > 0) { 4444df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project mItemCount = totalItemCount; 44532c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell mLongList = mItemCount / visibleItemCount >= MIN_PAGES; 44632c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell } 44732c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell if (mAlwaysShow) { 44832c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell mLongList = true; 4494df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 4504df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (!mLongList) { 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_NONE) { 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_NONE); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 456568ccd88d7efd33da0c535e07b7ea7cf476be22aAdam Powell if (totalItemCount - visibleItemCount > 0 && mState != STATE_DRAGGING) { 45732c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell mThumbY = getThumbPositionForListPosition(firstVisibleItem, visibleItemCount, 45832c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell totalItemCount); 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mChangedBounds) { 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetThumbPos(); 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChangedBounds = false; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScrollCompleted = true; 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (firstVisibleItem == mVisibleItem) { 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVisibleItem = firstVisibleItem; 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_DRAGGING) { 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_VISIBLE); 47120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (!mAlwaysShow) { 47220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mHandler.postDelayed(mScrollFade, FADE_TIMEOUT); 47320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 477d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy SectionIndexer getSectionIndexer() { 478d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy return mSectionIndexer; 479d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy } 480d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy 481d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy Object[] getSections() { 482d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy if (mListAdapter == null && mList != null) { 483d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy getSectionsFromIndexer(); 484d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy } 485d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy return mSections; 486d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy } 487d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy 488af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell void getSectionsFromIndexer() { 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Adapter adapter = mList.getAdapter(); 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSectionIndexer = null; 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter instanceof HeaderViewListAdapter) { 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListOffset = ((HeaderViewListAdapter)adapter).getHeadersCount(); 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter(); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter instanceof ExpandableListConnector) { 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListAdapter expAdapter = ((ExpandableListConnector)adapter).getAdapter(); 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (expAdapter instanceof SectionIndexer) { 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSectionIndexer = (SectionIndexer) expAdapter; 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListAdapter = (BaseAdapter) adapter; 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSections = mSectionIndexer.getSections(); 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter instanceof SectionIndexer) { 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListAdapter = (BaseAdapter) adapter; 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSectionIndexer = (SectionIndexer) adapter; 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSections = mSectionIndexer.getSections(); 507f49971ec06e65ee2a0f0fd48a615b89c677086e7Adam Powell if (mSections == null) { 508f49971ec06e65ee2a0f0fd48a615b89c677086e7Adam Powell mSections = new String[] { " " }; 509f49971ec06e65ee2a0f0fd48a615b89c677086e7Adam Powell } 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListAdapter = (BaseAdapter) adapter; 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSections = new String[] { " " }; 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 517b1f498afc379ec84b86137e91afda6eccb8f4c0aAdam Powell public void onSectionsChanged() { 518b1f498afc379ec84b86137e91afda6eccb8f4c0aAdam Powell mListAdapter = null; 519b1f498afc379ec84b86137e91afda6eccb8f4c0aAdam Powell } 520b1f498afc379ec84b86137e91afda6eccb8f4c0aAdam Powell 521af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell void scrollTo(float position) { 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mList.getCount(); 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScrollCompleted = false; 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float fThreshold = (1.0f / count) / 8; 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Object[] sections = mSections; 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int sectionIndex; 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sections != null && sections.length > 1) { 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int nSections = sections.length; 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int section = (int) (position * nSections); 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (section >= nSections) { 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project section = nSections - 1; 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int exactSection = section; 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sectionIndex = section; 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = mSectionIndexer.getPositionForSection(section); 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Given the expected section and index, the following code will 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // try to account for missing sections (no names starting with..) 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It will compute the scroll space of surrounding empty sections 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and interpolate the currently visible letter's range across the 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // available space, so that there is always some list movement while 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the user moves the thumb. 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextIndex = count; 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int prevIndex = index; 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int prevSection = section; 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextSection = section + 1; 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Assume the next section is unique 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (section < nSections - 1) { 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextIndex = mSectionIndexer.getPositionForSection(section + 1); 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find the previous index if we're slicing the previous section 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextIndex == index) { 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Non-existent letter 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (section > 0) { 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project section--; 556b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project prevIndex = mSectionIndexer.getPositionForSection(section); 557b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (prevIndex != index) { 558b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project prevSection = section; 559b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project sectionIndex = section; 560b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project break; 561b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } else if (section == 0) { 562b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // When section reaches 0 here, sectionIndex must follow it. 563b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // Assuming mSectionIndexer.getPositionForSection(0) == 0. 564b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project sectionIndex = 0; 565b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project break; 566b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find the next index, in case the assumed next index is not 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // unique. For instance, if there is no P, then request for P's 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // position actually returns Q's. So we need to look ahead to make 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sure that there is really a Q at Q's position. If not, move 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // further down... 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextNextSection = nextSection + 1; 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (nextNextSection < nSections && 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSectionIndexer.getPositionForSection(nextNextSection) == nextIndex) { 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextNextSection++; 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextSection++; 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Compute the beginning and ending scroll range percentage of the 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // currently visible letter. This could be equal to or greater than 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (1 / nSections). 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float fPrev = (float) prevSection / nSections; 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float fNext = (float) nextSection / nSections; 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prevSection == exactSection && position - fPrev < fThreshold) { 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = prevIndex; 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = prevIndex + (int) ((nextIndex - prevIndex) * (position - fPrev) 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project / (fNext - fPrev)); 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't overflow 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index > count - 1) index = count - 1; 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mList instanceof ExpandableListView) { 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListView expList = (ExpandableListView) mList; 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project expList.setSelectionFromTop(expList.getFlatListPosition( 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListView.getPackedPositionForGroup(index + mListOffset)), 0); 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mList instanceof ListView) { 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((ListView)mList).setSelectionFromTop(index + mListOffset, 0); 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.setSelection(index + mListOffset); 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = (int) (position * count); 6057ee1ff1450a3ff83b6b8663bd7f44dc6f30775afAdam Powell // Don't overflow 6067ee1ff1450a3ff83b6b8663bd7f44dc6f30775afAdam Powell if (index > count - 1) index = count - 1; 6077ee1ff1450a3ff83b6b8663bd7f44dc6f30775afAdam Powell 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mList instanceof ExpandableListView) { 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListView expList = (ExpandableListView) mList; 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project expList.setSelectionFromTop(expList.getFlatListPosition( 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListView.getPackedPositionForGroup(index + mListOffset)), 0); 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mList instanceof ListView) { 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((ListView)mList).setSelectionFromTop(index + mListOffset, 0); 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.setSelection(index + mListOffset); 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sectionIndex = -1; 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sectionIndex >= 0) { 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String text = mSectionText = sections[sectionIndex].toString(); 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawOverlay = (text.length() != 1 || text.charAt(0) != ' ') && 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sectionIndex < sections.length; 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDrawOverlay = false; 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 62932c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell private int getThumbPositionForListPosition(int firstVisibleItem, int visibleItemCount, 63032c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell int totalItemCount) { 63135948b7ed502d3f126acc8f2d61e099fa5deb0c7Adam Powell if (mSectionIndexer == null || mListAdapter == null) { 63232c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell getSectionsFromIndexer(); 63332c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell } 634568ccd88d7efd33da0c535e07b7ea7cf476be22aAdam Powell if (mSectionIndexer == null || !mMatchDragPosition) { 63532c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell return ((mList.getHeight() - mThumbH) * firstVisibleItem) 63632c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell / (totalItemCount - visibleItemCount); 63732c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell } 63832c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell 63932c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell firstVisibleItem -= mListOffset; 64032c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell if (firstVisibleItem < 0) { 64132c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell return 0; 64232c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell } 64332c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell totalItemCount -= mListOffset; 64432c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell 64532c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell final int trackHeight = mList.getHeight() - mThumbH; 64632c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell 64732c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell final int section = mSectionIndexer.getSectionForPosition(firstVisibleItem); 64832c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell final int sectionPos = mSectionIndexer.getPositionForSection(section); 64932c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell final int nextSectionPos = mSectionIndexer.getPositionForSection(section + 1); 650f49971ec06e65ee2a0f0fd48a615b89c677086e7Adam Powell final int sectionCount = mSections.length; 65132c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell final int positionsInSection = nextSectionPos - sectionPos; 65232c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell 65332c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell final View child = mList.getChildAt(0); 65432aa2c90ee6e12f6c53c7d572d5c02f1d795b8f7Adam Powell final float incrementalPos = child == null ? 0 : firstVisibleItem + 65532c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell (float) (mList.getPaddingTop() - child.getTop()) / child.getHeight(); 65632c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell final float posWithinSection = (incrementalPos - sectionPos) / positionsInSection; 65732c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell int result = (int) ((section + posWithinSection) / sectionCount * trackHeight); 65832c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell 65932c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell // Fake out the scrollbar for the last item. Since the section indexer won't 66032c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell // ever actually move the list in this end space, make scrolling across the last item 66132c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell // account for whatever space is remaining. 66232c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell if (firstVisibleItem > 0 && firstVisibleItem + visibleItemCount == totalItemCount) { 66332c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell final View lastChild = mList.getChildAt(visibleItemCount - 1); 66432c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell final float lastItemVisible = (float) (mList.getHeight() - mList.getPaddingBottom() 66532c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell - lastChild.getTop()) / lastChild.getHeight(); 66632c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell result += (trackHeight - result) * lastItemVisible; 66732c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell } 66832c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell 66932c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell return result; 67032c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell } 67132c3a6929af9d63de3bf45a61be6e1a4bde136d3Adam Powell 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void cancelFling() { 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Cancel the list fling 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MotionEvent cancelFling = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0); 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.onTouchEvent(cancelFling); 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cancelFling.recycle(); 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell void cancelPendingDrag() { 680af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mList.removeCallbacks(mDeferStartDrag); 681af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mPendingDrag = false; 682af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 683af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell 684af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell void startPendingDrag() { 685af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mPendingDrag = true; 686af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mList.postDelayed(mDeferStartDrag, PENDING_DRAG_DELAY); 687af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 688af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell 689af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell void beginDrag() { 690af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell setState(STATE_DRAGGING); 691af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell if (mListAdapter == null && mList != null) { 692af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell getSectionsFromIndexer(); 693af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 694af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell if (mList != null) { 695af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mList.requestDisallowInterceptTouchEvent(true); 696af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mList.reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 697af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 698af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell 699af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell cancelFling(); 700af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 701af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onInterceptTouchEvent(MotionEvent ev) { 703af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell switch (ev.getActionMasked()) { 704af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell case MotionEvent.ACTION_DOWN: 705af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell if (mState > STATE_NONE && isPointInside(ev.getX(), ev.getY())) { 706af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell if (!mList.isInScrollingContainer()) { 707af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell beginDrag(); 708af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell return true; 709af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 710af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mInitialTouchY = ev.getY(); 711af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell startPendingDrag(); 712af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 713af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell break; 714af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell case MotionEvent.ACTION_UP: 715af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell case MotionEvent.ACTION_CANCEL: 716af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell cancelPendingDrag(); 717af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell break; 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onTouchEvent(MotionEvent me) { 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_NONE) { 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 72682f3495b146b267f3786997752cef25310176349Romain Guy 72782f3495b146b267f3786997752cef25310176349Romain Guy final int action = me.getAction(); 72882f3495b146b267f3786997752cef25310176349Romain Guy 72982f3495b146b267f3786997752cef25310176349Romain Guy if (action == MotionEvent.ACTION_DOWN) { 73082f3495b146b267f3786997752cef25310176349Romain Guy if (isPointInside(me.getX(), me.getY())) { 731af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell if (!mList.isInScrollingContainer()) { 732af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell beginDrag(); 733af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell return true; 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 735af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mInitialTouchY = me.getY(); 736af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell startPendingDrag(); 737af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 738af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } else if (action == MotionEvent.ACTION_UP) { // don't add ACTION_CANCEL here 739af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell if (mPendingDrag) { 740af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell // Allow a tap to scroll. 741af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell beginDrag(); 742af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell 743af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell final int viewHeight = mList.getHeight(); 744af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell // Jitter 745af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell int newThumbY = (int) me.getY() - mThumbH + 10; 746af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell if (newThumbY < 0) { 747af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell newThumbY = 0; 748af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } else if (newThumbY + mThumbH > viewHeight) { 749af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell newThumbY = viewHeight - mThumbH; 750d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen } 751af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mThumbY = newThumbY; 752af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell scrollTo((float) mThumbY / (viewHeight - mThumbH)); 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 754af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell cancelPendingDrag(); 755af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell // Will hit the STATE_DRAGGING check below 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_DRAGGING) { 758d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen if (mList != null) { 759d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen // ViewGroup does the right thing already, but there might 760d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen // be other classes that don't properly reset on touch-up, 761d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen // so do this explicitly just in case. 762d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen mList.requestDisallowInterceptTouchEvent(false); 763d43bd48fe311fa6320e46ca9b9ce25241c476ac6Adam Powell mList.reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); 764d43fe07852a23c78da3b51b45469687c20be919aMarco Nelissen } 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_VISIBLE); 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Handler handler = mHandler; 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handler.removeCallbacks(mScrollFade); 76820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell if (!mAlwaysShow) { 76920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell handler.postDelayed(mScrollFade, 1000); 77020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 77120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 77220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell mList.invalidate(); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 77582f3495b146b267f3786997752cef25310176349Romain Guy } else if (action == MotionEvent.ACTION_MOVE) { 776af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell if (mPendingDrag) { 777af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell final float y = me.getY(); 778af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell if (Math.abs(y - mInitialTouchY) > mScaledTouchSlop) { 779af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell setState(STATE_DRAGGING); 780af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell if (mListAdapter == null && mList != null) { 781af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell getSectionsFromIndexer(); 782af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 783af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell if (mList != null) { 784af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mList.requestDisallowInterceptTouchEvent(true); 785af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell mList.reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 786af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 787af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell 788af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell cancelFling(); 789af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell cancelPendingDrag(); 790af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell // Will hit the STATE_DRAGGING check below 791af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 792af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_DRAGGING) { 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int viewHeight = mList.getHeight(); 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Jitter 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newThumbY = (int) me.getY() - mThumbH + 10; 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newThumbY < 0) { 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newThumbY = 0; 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (newThumbY + mThumbH > viewHeight) { 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newThumbY = viewHeight - mThumbH; 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Math.abs(mThumbY - newThumbY) < 2) { 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThumbY = newThumbY; 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the previous scrollTo is still pending 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mScrollCompleted) { 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollTo((float) mThumbY / (viewHeight - mThumbH)); 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 812af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell } else if (action == MotionEvent.ACTION_CANCEL) { 813af5280cc71e155758c2f6625eb999cabb37e937fAdam Powell cancelPendingDrag(); 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 817d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy 81882f3495b146b267f3786997752cef25310176349Romain Guy boolean isPointInside(float x, float y) { 81920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell boolean inTrack = false; 82020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell switch (mPosition) { 82120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell default: 82220232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_RIGHT: 82320232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell inTrack = x > mList.getWidth() - mThumbW; 82420232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 82520232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell case View.SCROLLBAR_POSITION_LEFT: 82620232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell inTrack = x < mThumbW; 82720232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell break; 82820232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell } 82920232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell 83020232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell // Allow taps in the track to start moving. 83120232d0f7ce2220df72dd78bed052f6b4a643f10Adam Powell return inTrack && (mTrackDrawable != null || y >= mThumbY && y <= mThumbY + mThumbH); 83282f3495b146b267f3786997752cef25310176349Romain Guy } 83382f3495b146b267f3786997752cef25310176349Romain Guy 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public class ScrollFade implements Runnable { 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mStartTime; 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long mFadeDuration; 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int ALPHA_MAX = 208; 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final long FADE_DURATION = 200; 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void startFade() { 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFadeDuration = FADE_DURATION; 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStartTime = SystemClock.uptimeMillis(); 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_EXIT); 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int getAlpha() { 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getState() != STATE_EXIT) { 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ALPHA_MAX; 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int alpha; 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = SystemClock.uptimeMillis(); 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (now > mStartTime + mFadeDuration) { 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = 0; 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alpha = (int) (ALPHA_MAX - ((now - mStartTime) * ALPHA_MAX) / mFadeDuration); 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return alpha; 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getState() != STATE_EXIT) { 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startFade(); 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getAlpha() > 0) { 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mList.invalidate(); 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setState(STATE_NONE); 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 875