diff options
| author | Alan Viverette <alanv@google.com> | 2013-06-07 11:43:06 -0700 |
|---|---|---|
| committer | Alan Viverette <alanv@google.com> | 2013-06-07 11:43:06 -0700 |
| commit | e918a48df92fd16375c46624df74e6fd4609e016 (patch) | |
| tree | 1ab8bb96ab6df824fdcf7e28c9b3bfbf3320f088 /core/java/android | |
| parent | 20b53f89fadb993f3edcd33c0d776c2dac6bd751 (diff) | |
Clean up FastScroller. Expand overlay to fit text content.
Bug: 6472526
Change-Id: I1b4d5ca87a1844d372553377294f9b7341f3bfd1
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/widget/FastScroller.java | 145 |
1 files changed, 81 insertions, 64 deletions
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java index fc9c000da773..aa33384e6fcb 100644 --- a/core/java/android/widget/FastScroller.java +++ b/core/java/android/widget/FastScroller.java @@ -18,6 +18,7 @@ package android.widget; import android.content.Context; import android.content.res.ColorStateList; +import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; @@ -37,12 +38,13 @@ import android.widget.AbsListView.OnScrollListener; */ class FastScroller { private static final String TAG = "FastScroller"; - + // Minimum number of pages to justify showing a fast scroll thumb private static int MIN_PAGES = 4; // Scroll thumb not showing private static final int STATE_NONE = 0; // Not implemented yet - fade-in transition + @SuppressWarnings("unused") private static final int STATE_ENTER = 1; // Scroll thumb visible and moving along with the scrollbar private static final int STATE_VISIBLE = 2; @@ -75,7 +77,7 @@ class FastScroller { private static final int OVERLAY_FLOATING = 0; private static final int OVERLAY_AT_THUMB = 1; - + private Drawable mThumbDrawable; private Drawable mOverlayDrawable; private Drawable mTrackDrawable; @@ -89,6 +91,7 @@ class FastScroller { private RectF mOverlayPos; private int mOverlaySize; + private int mOverlayPadding; AbsListView mList; boolean mScrollCompleted; @@ -97,21 +100,21 @@ class FastScroller { private int mListOffset; private int mItemCount = -1; private boolean mLongList; - + private Object [] mSections; private String mSectionText; private boolean mDrawOverlay; private ScrollFade mScrollFade; - + private int mState; - + private Handler mHandler = new Handler(); - + BaseAdapter mListAdapter; private SectionIndexer mSectionIndexer; private boolean mChangedBounds; - + private int mPosition; private boolean mAlwaysShow; @@ -130,6 +133,7 @@ class FastScroller { private final Rect mTmpRect = new Rect(); private final Runnable mDeferStartDrag = new Runnable() { + @Override public void run() { if (mList.mIsAttached) { beginDrag(); @@ -237,11 +241,11 @@ class FastScroller { mState = state; refreshDrawableState(); } - + public int getState() { return mState; } - + private void resetThumbPos() { final int viewWidth = mList.getWidth(); // Bounds are always top right. Y coordinate get's translated during draw @@ -255,7 +259,7 @@ class FastScroller { } mThumbDrawable.setAlpha(ScrollFade.ALPHA_MAX); } - + private void useThumbDrawable(Context context, Drawable drawable) { mThumbDrawable = drawable; if (drawable instanceof NinePatchDrawable) { @@ -272,20 +276,23 @@ class FastScroller { private void init(Context context) { // Get both the scrollbar states drawables - TypedArray ta = context.getTheme().obtainStyledAttributes(ATTRS); + final TypedArray ta = context.getTheme().obtainStyledAttributes(ATTRS); useThumbDrawable(context, ta.getDrawable(THUMB_DRAWABLE)); mTrackDrawable = ta.getDrawable(TRACK_DRAWABLE); - + mOverlayDrawableLeft = ta.getDrawable(PREVIEW_BACKGROUND_LEFT); mOverlayDrawableRight = ta.getDrawable(PREVIEW_BACKGROUND_RIGHT); mOverlayPosition = ta.getInt(OVERLAY_POSITION, OVERLAY_FLOATING); - + mScrollCompleted = true; getSectionsFromIndexer(); - mOverlaySize = context.getResources().getDimensionPixelSize( + final Resources res = context.getResources(); + mOverlaySize = res.getDimensionPixelSize( com.android.internal.R.dimen.fastscroll_overlay_size); + mOverlayPadding = res.getDimensionPixelSize( + com.android.internal.R.dimen.fastscroll_overlay_padding); mOverlayPos = new RectF(); mScrollFade = new ScrollFade(); mPaint = new Paint(); @@ -302,7 +309,7 @@ class FastScroller { if (mList.getWidth() > 0 && mList.getHeight() > 0) { onSizeChanged(mList.getWidth(), mList.getHeight(), 0, 0); } - + mState = STATE_NONE; refreshDrawableState(); @@ -315,17 +322,17 @@ class FastScroller { setScrollbarPosition(mList.getVerticalScrollbarPosition()); } - + void stop() { setState(STATE_NONE); } - + boolean isVisible() { return !(mState == STATE_NONE); } - + public void draw(Canvas canvas) { - + if (mState == STATE_NONE) { // No need to draw anything return; @@ -371,44 +378,53 @@ class FastScroller { // If user is dragging the scroll bar, draw the alphabet overlay if (mState == STATE_DRAGGING && mDrawOverlay) { + final Drawable overlay = mOverlayDrawable; + final Paint paint = mPaint; + final String sectionText = mSectionText; + final Rect tmpRect = mTmpRect; + + // TODO: Use a text view in an overlay for transition animations and + // handling of text overflow. + paint.getTextBounds(sectionText, 0, sectionText.length(), tmpRect); + final int textWidth = tmpRect.width(); + final int textHeight = tmpRect.height(); + + overlay.getPadding(tmpRect); + final int overlayWidth = Math.max( + mOverlaySize, textWidth + tmpRect.left + tmpRect.right + mOverlayPadding * 2); + final int overlayHeight = Math.max( + mOverlaySize, textHeight + tmpRect.top + tmpRect.bottom + mOverlayPadding * 2); + final RectF pos = mOverlayPos; + if (mOverlayPosition == OVERLAY_AT_THUMB) { - int left = 0; + final Rect thumbBounds = mThumbDrawable.getBounds(); + switch (mPosition) { - default: - case View.SCROLLBAR_POSITION_RIGHT: - left = Math.max(0, - mThumbDrawable.getBounds().left - mThumbW - mOverlaySize); - break; case View.SCROLLBAR_POSITION_LEFT: - left = Math.min(mThumbDrawable.getBounds().right + mThumbW, - mList.getWidth() - mOverlaySize); + pos.left = Math.min( + thumbBounds.right + mThumbW, mList.getWidth() - overlayWidth); + break; + case View.SCROLLBAR_POSITION_RIGHT: + default: + pos.left = Math.max(0, thumbBounds.left - mThumbW - overlayWidth); break; } - int top = Math.max(0, - Math.min(y + (mThumbH - mOverlaySize) / 2, mList.getHeight() - mOverlaySize)); - - final RectF pos = mOverlayPos; - pos.left = left; - pos.right = pos.left + mOverlaySize; - pos.top = top; - pos.bottom = pos.top + mOverlaySize; - if (mOverlayDrawable != null) { - mOverlayDrawable.setBounds((int) pos.left, (int) pos.top, - (int) pos.right, (int) pos.bottom); - } + pos.top = Math.max(0, Math.min( + y + (mThumbH - overlayHeight) / 2, mList.getHeight() - overlayHeight)); } - mOverlayDrawable.draw(canvas); - final Paint paint = mPaint; - float descent = paint.descent(); - final RectF rectF = mOverlayPos; - final Rect tmpRect = mTmpRect; - mOverlayDrawable.getPadding(tmpRect); - final int hOff = (tmpRect.right - tmpRect.left) / 2; - final int vOff = (tmpRect.bottom - tmpRect.top) / 2; - canvas.drawText(mSectionText, (int) (rectF.left + rectF.right) / 2 - hOff, - (int) (rectF.bottom + rectF.top) / 2 + mOverlaySize / 4 - descent - vOff, - paint); + + pos.right = pos.left + overlayWidth; + pos.bottom = pos.top + overlayHeight; + + overlay.setBounds((int) pos.left, (int) pos.top, (int) pos.right, (int) pos.bottom); + overlay.draw(canvas); + + final float hOff = (tmpRect.right - tmpRect.left) / 2.0f; + final float vOff = (tmpRect.bottom - tmpRect.top) / 2.0f; + final float cX = pos.centerX() - hOff; + final float cY = pos.centerY() + (overlayHeight / 4.0f) - paint.descent() - vOff; + canvas.drawText(mSectionText, cX, cY, paint); } else if (mState == STATE_EXIT) { if (alpha == 0) { // Done with exit setState(STATE_NONE); @@ -467,7 +483,7 @@ class FastScroller { } } - void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, + void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // Are there enough pages to require fast scroll? Recompute only if total count changes if (mItemCount != totalItemCount && visibleItemCount > 0) { @@ -577,7 +593,7 @@ class FastScroller { if (section < nSections - 1) { nextIndex = mSectionIndexer.getPositionForSection(section + 1); } - + // Find the previous index if we're slicing the previous section if (nextIndex == index) { // Non-existent letter @@ -597,9 +613,9 @@ class FastScroller { } } // Find the next index, in case the assumed next index is not - // unique. For instance, if there is no P, then request for P's + // unique. For instance, if there is no P, then request for P's // position actually returns Q's. So we need to look ahead to make - // sure that there is really a Q at Q's position. If not, move + // sure that there is really a Q at Q's position. If not, move // further down... int nextNextSection = nextSection + 1; while (nextNextSection < nSections && @@ -609,18 +625,18 @@ class FastScroller { } // Compute the beginning and ending scroll range percentage of the // currently visible letter. This could be equal to or greater than - // (1 / nSections). + // (1 / nSections). float fPrev = (float) prevSection / nSections; float fNext = (float) nextSection / nSections; if (prevSection == exactSection && position - fPrev < fThreshold) { index = prevIndex; } else { - index = prevIndex + (int) ((nextIndex - prevIndex) * (position - fPrev) + index = prevIndex + (int) ((nextIndex - prevIndex) * (position - fPrev) / (fNext - fPrev)); } // Don't overflow if (index > count - 1) index = count - 1; - + if (mList instanceof ExpandableListView) { ExpandableListView expList = (ExpandableListView) mList; expList.setSelectionFromTop(expList.getFlatListPosition( @@ -705,7 +721,7 @@ class FastScroller { mList.onTouchEvent(cancelFling); cancelFling.recycle(); } - + void cancelPendingDrag() { mList.removeCallbacks(mDeferStartDrag); mPendingDrag = false; @@ -862,18 +878,18 @@ class FastScroller { } public class ScrollFade implements Runnable { - + long mStartTime; long mFadeDuration; static final int ALPHA_MAX = 208; static final long FADE_DURATION = 200; - + void startFade() { mFadeDuration = FADE_DURATION; mStartTime = SystemClock.uptimeMillis(); setState(STATE_EXIT); } - + int getAlpha() { if (getState() != STATE_EXIT) { return ALPHA_MAX; @@ -883,17 +899,18 @@ class FastScroller { if (now > mStartTime + mFadeDuration) { alpha = 0; } else { - alpha = (int) (ALPHA_MAX - ((now - mStartTime) * ALPHA_MAX) / mFadeDuration); + alpha = (int) (ALPHA_MAX - ((now - mStartTime) * ALPHA_MAX) / mFadeDuration); } return alpha; } - + + @Override public void run() { if (getState() != STATE_EXIT) { startFade(); return; } - + if (getAlpha() > 0) { mList.invalidate(); } else { |
