GridView的平滑滚动

时间:2012-01-17 23:35:06

标签: android gridview scroll position smooth-scrolling

smoothScrollToPosition()的{​​{1}}方法是否正常工作? 我找到了一个开放的bug report,但我的工作也不正常。

GridView工作正常,但我想要一个流畅的滚动效果。

你对这个问题有任何想法吗?

如果这是一个持久性问题,我应该从哪里开始实现良好的滚动效果?

2 个答案:

答案 0 :(得分:3)

虽然我没有看到运行您发布的示例代码的任何问题,但如果您在应用程序中看不到一致的结果,那么创建自己的滚动控制器并不是太棘手。以下是您可以使用的示例实现:

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);
    }
}

以下是您链接的示例的片段,其中包含此新类的位置,以代替框架实现进行滚动:

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;
    }
}

如果要添加一个功能,即使滚动方向向下,所选位置也始终滚动到顶部,您可以这样做。 这不是框架实现的目的,但您可以通过在DIR_DOWN中添加一些代码来继续滚动直到第一个可见位置与目标匹配(如{{1} })。您还必须注意滚动在位置到达顶部之前结束的情况,因此在您永远不会得到不同结果的情况下,您不会经常发布处理程序。

HTH

答案 1 :(得分:1)

有同样的问题 - 我构建了一个简单的GridView,由于某些原因,smoothScrollToPosition()根本不起作用(只是不时反弹)。

经过大量调试后发现我需要从GridView中删除android:padding参数。

很奇怪,我真的不知道为什么会这样,但至少现在它有效。