private int getThumbPositionForListPosition(int firstVisibleItem, int visibleItemCount , int totalItemCount) { if (mSectionIndexer == null || mListAdapter == null) { getSectionsFromIndexer(); } if (mSectionIndexer == null || !mMatchDragPosition) { return(((mList.getHeight() - mThumbH) * firstVisibleItem) / (totalItemCount - visibleItemCount )); } firstVisibleItem -= mListOffset; if (firstVisibleItem < 0) { return(0); } totalItemCount -= mListOffset; int trackHeight = mList.getHeight() - mThumbH; int section = mSectionIndexer.getSectionForPosition(firstVisibleItem); int sectionPos = mSectionIndexer.getPositionForSection(section); int nextSectionPos = mSectionIndexer.getPositionForSection(section + 1); int sectionCount = mSections.Length; int positionsInSection = nextSectionPos - sectionPos; android.view.View child = mList.getChildAt(0); float incrementalPos = child == null ? 0 : firstVisibleItem + (float)(mList.getPaddingTop () - child.getTop()) / child.getHeight(); 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) { android.view.View lastChild = mList.getChildAt(visibleItemCount - 1); float lastItemVisible = (float)(mList.getHeight() - mList.getPaddingBottom() - lastChild .getTop()) / lastChild.getHeight(); result += (int)((trackHeight - result) * lastItemVisible); } return(result); }
/// <summary> /// Will forward touch events to the delegate view if the event is within the bounds /// specified in the constructor. /// </summary> /// <remarks> /// Will forward touch events to the delegate view if the event is within the bounds /// specified in the constructor. /// </remarks> /// <param name="event">The touch event to forward</param> /// <returns>True if the event was forwarded to the delegate, false otherwise.</returns> public virtual bool onTouchEvent(android.view.MotionEvent @event) { int x = (int)@event.getX(); int y = (int)@event.getY(); bool sendToDelegate = false; bool hit = true; bool handled = false; switch (@event.getAction()) { case android.view.MotionEvent.ACTION_DOWN: { android.graphics.Rect bounds = mBounds; if (bounds.contains(x, y)) { mDelegateTargeted = true; sendToDelegate = true; } break; } case android.view.MotionEvent.ACTION_UP: case android.view.MotionEvent.ACTION_MOVE: { sendToDelegate = mDelegateTargeted; if (sendToDelegate) { android.graphics.Rect slopBounds = mSlopBounds; if (!slopBounds.contains(x, y)) { hit = false; } } break; } case android.view.MotionEvent.ACTION_CANCEL: { sendToDelegate = mDelegateTargeted; mDelegateTargeted = false; break; } } if (sendToDelegate) { android.view.View delegateView = mDelegateView; if (hit) { // Offset event coordinates to be inside the target view @event.setLocation(delegateView.getWidth() / 2, delegateView.getHeight() / 2); } else { // Offset event coordinates to be outside the target view (in case it does // something like tracking pressed state) int slop = mSlop; @event.setLocation(-(slop * 2), -(slop * 2)); } handled = delegateView.dispatchTouchEvent(@event); } return(handled); }