Until I see any problems with the running code of the example that you posted, if you do not see consistent results in your application, it is not too difficult to create your own scroll controller. Here is an example implementation that you could use:
private class ScrollPositioner { private static final int SCROLL_DURATION = 20; private static final int DIR_UP = 1; private static final int DIR_DOWN = 2; int mTargetPosition = AdapterView.INVALID_POSITION; int mDirection = AdapterView.INVALID_POSITION; int mLastSeenPosition = AdapterView.INVALID_POSITION; int mExtraScroll; GridView mGrid; public ScrollPositioner(GridView grid) { mGrid = grid; mExtraScroll = ViewConfiguration.get(mGrid.getContext()).getScaledFadingEdgeLength(); } Handler mHandler = new Handler(); Runnable mScroller = new Runnable() { public void run() { int firstPos = mGrid.getFirstVisiblePosition(); switch(mDirection) { case DIR_UP: { if (firstPos == mLastSeenPosition) { // No new views, let things keep going. mHandler.postDelayed(mScroller, SCROLL_DURATION); return; } final View firstView = mGrid.getChildAt(0); if (firstView == null) { return; } final int firstViewTop = firstView.getTop(); final int extraScroll = firstPos > 0 ? mExtraScroll : mGrid.getPaddingTop(); mGrid.smoothScrollBy(firstViewTop - extraScroll, SCROLL_DURATION); mLastSeenPosition = firstPos; if (firstPos > mTargetPosition) { mHandler.postDelayed(mScroller, SCROLL_DURATION); } break; } case DIR_DOWN: { final int lastViewIndex = mGrid.getChildCount() - 1; final int lastPos = firstPos + lastViewIndex; if (lastViewIndex < 0) { return; } if (lastPos == mLastSeenPosition) { // No new views, let things keep going. mHandler.postDelayed(mScroller, SCROLL_DURATION); return; } final View lastView = mGrid.getChildAt(lastViewIndex); final int lastViewHeight = lastView.getHeight(); final int lastViewTop = lastView.getTop(); final int lastViewPixelsShowing = mGrid.getHeight() - lastViewTop; final int extraScroll = lastPos < mGrid.getAdapter().getCount() - 1 ? mExtraScroll : mGrid.getPaddingBottom(); mGrid.smoothScrollBy(lastViewHeight - lastViewPixelsShowing + extraScroll, SCROLL_DURATION); mLastSeenPosition = lastPos; if (lastPos < mTargetPosition) { mHandler.postDelayed(mScroller, SCROLL_DURATION); } break; } default: break; } } }; public void scrollToPosition(int position) { mTargetPosition = position; mLastSeenPosition = AdapterView.INVALID_POSITION; if(position < mGrid.getFirstVisiblePosition()) { mDirection = DIR_UP; } else if (position > mGrid.getLastVisiblePosition()) { mDirection = DIR_DOWN; } else { return; } mHandler.post(mScroller); } }
Here is a snippet from the example you gave, which includes where this new class performs scrolling instead of implementing the framework:
GridView g; boolean t= false; @Override public void onBackPressed() { //Instantiate and attach the custom positioner if(mPositioner == null) { mPositioner = new ScrollPositioner(g); } //Use the custom object to scroll the view mPositioner.scrollToPosition(0); if(t) { super.onBackPressed(); } else { t = true; } }
If you want to add a function in which the selected position always scrolls up, even when the scroll direction is down, you can do it. This is not something that is implemented as part of the implementation of the framework , but you can execute it by adding some code to DIR_DOWN to continue scrolling until the first visible position matches the target (for example, DIR_UP ). You should also beware of a case where the scroll ends before the position reaches the top, so you do not constantly publish a handler in cases where you will never get another result.
NTN
source share