Methods Summary |
---|
private void | cancelFling()
// Cancel the list fling
MotionEvent cancelFling = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
mList.onTouchEvent(cancelFling);
cancelFling.recycle();
|
public void | draw(android.graphics.Canvas canvas)
if (mState == STATE_NONE) {
// No need to draw anything
return;
}
final int y = mThumbY;
final int viewWidth = mList.getWidth();
final FastScroller.ScrollFade scrollFade = mScrollFade;
int alpha = -1;
if (mState == STATE_EXIT) {
alpha = scrollFade.getAlpha();
if (alpha < ScrollFade.ALPHA_MAX / 2) {
mThumbDrawable.setAlpha(alpha * 2);
}
int left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX;
mThumbDrawable.setBounds(left, 0, viewWidth, mThumbH);
mChangedBounds = true;
}
canvas.translate(0, y);
mThumbDrawable.draw(canvas);
canvas.translate(0, -y);
// If user is dragging the scroll bar, draw the alphabet overlay
if (mState == STATE_DRAGGING && mDrawOverlay) {
mOverlayDrawable.draw(canvas);
final Paint paint = mPaint;
float descent = paint.descent();
final RectF rectF = mOverlayPos;
canvas.drawText(mSectionText, (int) (rectF.left + rectF.right) / 2,
(int) (rectF.bottom + rectF.top) / 2 + mOverlaySize / 4 - descent, paint);
} else if (mState == STATE_EXIT) {
if (alpha == 0) { // Done with exit
setState(STATE_NONE);
} else {
mList.invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH);
}
}
|
private void | getSections()
Adapter adapter = mList.getAdapter();
mSectionIndexer = null;
if (adapter instanceof HeaderViewListAdapter) {
mListOffset = ((HeaderViewListAdapter)adapter).getHeadersCount();
adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter();
}
if (adapter instanceof ExpandableListConnector) {
ExpandableListAdapter expAdapter = ((ExpandableListConnector)adapter).getAdapter();
if (expAdapter instanceof SectionIndexer) {
mSectionIndexer = (SectionIndexer) expAdapter;
mListAdapter = (BaseAdapter) adapter;
mSections = mSectionIndexer.getSections();
}
} else {
if (adapter instanceof SectionIndexer) {
mListAdapter = (BaseAdapter) adapter;
mSectionIndexer = (SectionIndexer) adapter;
mSections = mSectionIndexer.getSections();
} else {
mListAdapter = (BaseAdapter) adapter;
mSections = new String[] { " " };
}
}
|
public int | getState()
return mState;
|
private void | init(android.content.Context context)
// Get both the scrollbar states drawables
final Resources res = context.getResources();
useThumbDrawable(res.getDrawable(
com.android.internal.R.drawable.scrollbar_handle_accelerated_anim2));
mOverlayDrawable = res.getDrawable(
com.android.internal.R.drawable.menu_submenu_background);
mScrollCompleted = true;
getSections();
mOverlayPos = new RectF();
mScrollFade = new ScrollFade();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTextSize(mOverlaySize / 2);
TypedArray ta = context.getTheme().obtainStyledAttributes(new int[] {
android.R.attr.textColorPrimary });
ColorStateList textColor = ta.getColorStateList(ta.getIndex(0));
int textColorNormal = textColor.getDefaultColor();
mPaint.setColor(textColorNormal);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mState = STATE_NONE;
|
boolean | isVisible()
return !(mState == STATE_NONE);
|
boolean | onInterceptTouchEvent(android.view.MotionEvent ev)
if (mState > STATE_NONE && ev.getAction() == MotionEvent.ACTION_DOWN) {
if (ev.getX() > mList.getWidth() - mThumbW && ev.getY() >= mThumbY &&
ev.getY() <= mThumbY + mThumbH) {
setState(STATE_DRAGGING);
return true;
}
}
return false;
|
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) {
mItemCount = totalItemCount;
mLongList = mItemCount / visibleItemCount >= MIN_PAGES;
}
if (!mLongList) {
if (mState != STATE_NONE) {
setState(STATE_NONE);
}
return;
}
if (totalItemCount - visibleItemCount > 0 && mState != STATE_DRAGGING ) {
mThumbY = ((mList.getHeight() - mThumbH) * firstVisibleItem)
/ (totalItemCount - visibleItemCount);
if (mChangedBounds) {
resetThumbPos();
mChangedBounds = false;
}
}
mScrollCompleted = true;
if (firstVisibleItem == mVisibleItem) {
return;
}
mVisibleItem = firstVisibleItem;
if (mState != STATE_DRAGGING) {
setState(STATE_VISIBLE);
mHandler.postDelayed(mScrollFade, 1500);
}
|
void | onSizeChanged(int w, int h, int oldw, int oldh)
if (mThumbDrawable != null) {
mThumbDrawable.setBounds(w - mThumbW, 0, w, mThumbH);
}
final RectF pos = mOverlayPos;
pos.left = (w - mOverlaySize) / 2;
pos.right = pos.left + mOverlaySize;
pos.top = h / 10; // 10% from top
pos.bottom = pos.top + mOverlaySize;
if (mOverlayDrawable != null) {
mOverlayDrawable.setBounds((int) pos.left, (int) pos.top,
(int) pos.right, (int) pos.bottom);
}
|
boolean | onTouchEvent(android.view.MotionEvent me)
if (mState == STATE_NONE) {
return false;
}
if (me.getAction() == MotionEvent.ACTION_DOWN) {
if (me.getX() > mList.getWidth() - mThumbW
&& me.getY() >= mThumbY
&& me.getY() <= mThumbY + mThumbH) {
setState(STATE_DRAGGING);
if (mListAdapter == null && mList != null) {
getSections();
}
cancelFling();
return true;
}
} else if (me.getAction() == MotionEvent.ACTION_UP) {
if (mState == STATE_DRAGGING) {
setState(STATE_VISIBLE);
final Handler handler = mHandler;
handler.removeCallbacks(mScrollFade);
handler.postDelayed(mScrollFade, 1000);
return true;
}
} else if (me.getAction() == MotionEvent.ACTION_MOVE) {
if (mState == STATE_DRAGGING) {
final int viewHeight = mList.getHeight();
// Jitter
int newThumbY = (int) me.getY() - mThumbH + 10;
if (newThumbY < 0) {
newThumbY = 0;
} else if (newThumbY + mThumbH > viewHeight) {
newThumbY = viewHeight - mThumbH;
}
if (Math.abs(mThumbY - newThumbY) < 2) {
return true;
}
mThumbY = newThumbY;
// If the previous scrollTo is still pending
if (mScrollCompleted) {
scrollTo((float) mThumbY / (viewHeight - mThumbH));
}
return true;
}
}
return false;
|
private void | resetThumbPos()
final int viewWidth = mList.getWidth();
// Bounds are always top right. Y coordinate get's translated during draw
mThumbDrawable.setBounds(viewWidth - mThumbW, 0, viewWidth, mThumbH);
mThumbDrawable.setAlpha(ScrollFade.ALPHA_MAX);
|
private void | scrollTo(float position)
int count = mList.getCount();
mScrollCompleted = false;
float fThreshold = (1.0f / count) / 8;
final Object[] sections = mSections;
int sectionIndex;
if (sections != null && sections.length > 1) {
final int nSections = sections.length;
int section = (int) (position * nSections);
if (section >= nSections) {
section = nSections - 1;
}
int exactSection = section;
sectionIndex = section;
int index = mSectionIndexer.getPositionForSection(section);
// Given the expected section and index, the following code will
// try to account for missing sections (no names starting with..)
// It will compute the scroll space of surrounding empty sections
// and interpolate the currently visible letter's range across the
// available space, so that there is always some list movement while
// the user moves the thumb.
int nextIndex = count;
int prevIndex = index;
int prevSection = section;
int nextSection = section + 1;
// Assume the next section is unique
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
while (section > 0) {
section--;
prevIndex = mSectionIndexer.getPositionForSection(section);
if (prevIndex != index) {
prevSection = section;
sectionIndex = section;
break;
} else if (section == 0) {
// When section reaches 0 here, sectionIndex must follow it.
// Assuming mSectionIndexer.getPositionForSection(0) == 0.
sectionIndex = 0;
break;
}
}
}
// 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
// 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
// further down...
int nextNextSection = nextSection + 1;
while (nextNextSection < nSections &&
mSectionIndexer.getPositionForSection(nextNextSection) == nextIndex) {
nextNextSection++;
nextSection++;
}
// Compute the beginning and ending scroll range percentage of the
// currently visible letter. This could be equal to or greater than
// (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)
/ (fNext - fPrev));
}
// Don't overflow
if (index > count - 1) index = count - 1;
if (mList instanceof ExpandableListView) {
ExpandableListView expList = (ExpandableListView) mList;
expList.setSelectionFromTop(expList.getFlatListPosition(
ExpandableListView.getPackedPositionForGroup(index + mListOffset)), 0);
} else if (mList instanceof ListView) {
((ListView)mList).setSelectionFromTop(index + mListOffset, 0);
} else {
mList.setSelection(index + mListOffset);
}
} else {
int index = (int) (position * count);
if (mList instanceof ExpandableListView) {
ExpandableListView expList = (ExpandableListView) mList;
expList.setSelectionFromTop(expList.getFlatListPosition(
ExpandableListView.getPackedPositionForGroup(index + mListOffset)), 0);
} else if (mList instanceof ListView) {
((ListView)mList).setSelectionFromTop(index + mListOffset, 0);
} else {
mList.setSelection(index + mListOffset);
}
sectionIndex = -1;
}
if (sectionIndex >= 0) {
String text = mSectionText = sections[sectionIndex].toString();
mDrawOverlay = (text.length() != 1 || text.charAt(0) != ' ") &&
sectionIndex < sections.length;
} else {
mDrawOverlay = false;
}
|
public void | setState(int state)
switch (state) {
case STATE_NONE:
mHandler.removeCallbacks(mScrollFade);
mList.invalidate();
break;
case STATE_VISIBLE:
if (mState != STATE_VISIBLE) { // Optimization
resetThumbPos();
}
// Fall through
case STATE_DRAGGING:
mHandler.removeCallbacks(mScrollFade);
break;
case STATE_EXIT:
int viewWidth = mList.getWidth();
mList.invalidate(viewWidth - mThumbW, mThumbY, viewWidth, mThumbY + mThumbH);
break;
}
mState = state;
|
void | stop()
setState(STATE_NONE);
|
private void | useThumbDrawable(android.graphics.drawable.Drawable drawable)
mThumbDrawable = drawable;
mThumbW = 64; //mCurrentThumb.getIntrinsicWidth();
mThumbH = 52; //mCurrentThumb.getIntrinsicHeight();
mChangedBounds = true;
|