Code example for AbsListView

Methods: getAdapter, getWidth, onTouchEvent, requestDisallowInterceptTouchEvent

0
mChangedBounds = true;
	} 
 
	private void resetThumbPos() { 
		final int viewWidth = mList.getWidth();
		mThumbDrawable.setBounds(viewWidth - mThumbW, 0, viewWidth, mThumbH);
		mThumbDrawable.setAlpha(ScrollFade.ALPHA_MAX);
	} 
 
	private void getSectionsFromIndexer() { 
		Adapter adapter = mList.getAdapter();
		mSectionIndexer = null;
 
		if (!mFastScrollEnabled) {
			mListAdapter = (BaseAdapter) adapter;
			mSections = new String[] { " " };
			return; 
		} 
 
		if (adapter instanceof HeaderViewListAdapter) {
			mListOffset = ((HeaderViewListAdapter) adapter).getHeadersCount();
			adapter = ((HeaderViewListAdapter) adapter).getWrappedAdapter();
		} 
 
		if (adapter instanceof SectionIndexer) {
			mListAdapter = (BaseAdapter) adapter;
			mSectionIndexer = (SectionIndexer) adapter;
			mSections = mSectionIndexer.getSections();
			if (mSections == null) {
				mSections = new String[] { " " };
			} 
		} else { 
			mListAdapter = (BaseAdapter) adapter;
			mSections = new String[] { " " };
		} 
	} 
 
	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 ListView) {
				((ListView) mList).setSelectionFromTop(index + mListOffset, 0);
			} else { 
				mList.setSelection(index + mListOffset);
			} 
		} else { 
			int index = (int) (position * count);
			// 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);
			} 
			sectionIndex = -1;
		} 
 
		if (sectionIndex >= 0) {
			String text = mSectionText = sections[sectionIndex].toString();
			mDrawOverlay = (text.length() != 1 || text.charAt(0) != ' ') && sectionIndex < sections.length;
		} else { 
			mDrawOverlay = false;
		} 
	} 
 
	private int getThumbPositionForListPosition(int firstVisibleItem, int visibleItemCount, int totalItemCount) {
		if (mSectionIndexer == null || mListAdapter == null) {
			getSectionsFromIndexer(); 
		} 
		if (mSectionIndexer == null || !mMatchDragPosition) {
			int position = ((mList.getHeight() - mThumbH) * firstVisibleItem) / (totalItemCount - visibleItemCount);
			return position;
		} 
 
		firstVisibleItem -= mListOffset;
		if (firstVisibleItem < 0) {
			return 0; 
		} 
		totalItemCount -= mListOffset;
 
		final int trackHeight = mList.getHeight() - mThumbH;
 
		final int section = mSectionIndexer.getSectionForPosition(firstVisibleItem);
		final int sectionPos = mSectionIndexer.getPositionForSection(section);
		final int nextSectionPos = mSectionIndexer.getPositionForSection(section + 1);
		final int sectionCount = mSections.length;
		final int positionsInSection = nextSectionPos - sectionPos;
 
		final View child = mList.getChildAt(0);
		final float incrementalPos = child == null ? 0 : firstVisibleItem
				+ (float) (mList.getPaddingTop() - child.getTop()) / child.getHeight();
		final float posWithinSection = (incrementalPos - sectionPos) / positionsInSection;
		int result = (int) ((section + posWithinSection) / sectionCount * trackHeight);
 
		// Fake out the scrollbar for the last item. Since the section indexer 
		// won't 
		// ever actually move the list in this end space, make scrolling across 
		// the last item 
		// account for whatever space is remaining. 
		if (firstVisibleItem > 0 && firstVisibleItem + visibleItemCount == totalItemCount) {
			final View lastChild = mList.getChildAt(visibleItemCount - 1);
			final float lastItemVisible = (float) (mList.getHeight() - mList.getPaddingBottom() - lastChild.getTop())
					/ lastChild.getHeight();
			result += (trackHeight - result) * lastItemVisible;
		} 
 
		return result;
	} 
 
	private boolean isPointInside(float x, float y) {
		boolean inTrack = x > mList.getWidth() - mThumbW;
 
		// Allow taps in the track to start moving. 
		return inTrack && y >= mThumbY && y <= mThumbY + mThumbH;
	} 
 
	private void cancelFling() { 
		// Cancel the list fling 
		MotionEvent cancelFling = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
		mList.onTouchEvent(cancelFling);
		cancelFling.recycle();
	} 
 
	private void cancelPendingDrag() { 
		mList.removeCallbacks(mDeferStartDrag);
		mPendingDrag = false;
	} 
 
	@SuppressWarnings("unused") 
	private void startPendingDrag() { 
		mPendingDrag = true;
		mList.postDelayed(mDeferStartDrag, PENDING_DRAG_DELAY);
	} 
 
	private void beginDrag() { 
		setState(STATE_DRAGGING);
		if (mListAdapter == null && mList != null) {
			getSectionsFromIndexer(); 
		} 
		if (mList != null) {
			mList.requestDisallowInterceptTouchEvent(true);
			// !!! 
			// mList.reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 
		} 
 
		cancelFling();