GridView 的平滑滚动 [英] Smooth Scroll for GridView

查看:35
本文介绍了GridView 的平滑滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

GridViewsmoothScrollToPosition() 方法是否正常工作?我找到了一个开放的错误报告,但我的无法正常工作要么.

Does smoothScrollToPosition() method for GridView works correctly? I have found an open bug report and mine is not working correctly either.

setSelection() 工作正常,但我想要平滑的滚动效果.

setSelection() is working fine but I want a smooth scroll effect.

您对这个问题有什么想法吗?

Do you have any idea about this issue?

如果这是一个长期存在的问题,我应该从哪里开始实现一个好的滚动效果?

If this is a persistent problem, where should I start to implement a good scroll effect?

推荐答案

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

While I'm not seeing any issues running the example code you posted, if you're not seeing consistent results in your application it's not too tricky to create your own scroll controller. Here's an example implementation 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's a snippet from the example you linked that includes where this new class to do the scrolling in place of the framework implementation:

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中添加一些代码来继续滚动,直到第一个可见位置与目标匹配(例如DIR_UP 确实如此).您还必须注意滚动在位置到达顶部之前结束的情况,因此您不会在永远不会得到不同结果的情况下不断发布处理程序.

If you want to add a feature where the selected position is always scrolled to the top even when the scrolling direction is down, you could do that. This is not something the framework's implementation is designed to do, but you could accomplish it by adding some code in DIR_DOWN to continue scrolling until the first visible position matches target (like DIR_UP does). You must also beware of the case where the scrolling ends before the position reaches the top, so you aren't constantly posting the handler in cases where you will never get a different result.

HTH

这篇关于GridView 的平滑滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆