Java 修改ListView';s平滑拓扑变换

Java 修改ListView';s平滑拓扑变换,java,android,listview,scroll,customization,Java,Android,Listview,Scroll,Customization,调用smoothScrollToPosition时,ListView的默认行为是以线性速度移动到指定位置 深入研究ListView和AbsListView的代码,我可以看到发生这种行为是因为AbsListView使用一个定位器滚动器对象(实现AbsPositionScroller),该对象反过来使用一个FlingRunnable对象,在该对象上使用linear=true调用startScroll方法(最终使其OverScroller对象使用LinearInterpolator) 我想修改这个行为

调用smoothScrollToPosition时,ListView的默认行为是以线性速度移动到指定位置

深入研究ListView和AbsListView的代码,我可以看到发生这种行为是因为AbsListView使用一个定位器滚动器对象(实现AbsPositionScroller),该对象反过来使用一个FlingRunnable对象,在该对象上使用linear=true调用startScroll方法(最终使其OverScroller对象使用LinearInterpolator)

我想修改这个行为,让它使用OverScroller类默认使用的Scroller.ViscousFluidInterpolator类,但我没有找到一种方法

我看到AblistView定义了一个AbsPosScroller接口(他自己用一个PositionScroller类实现),我可以尝试用我自己的类来实现它,最终使用ViscousFluidInterpolator,但由于某些原因,这个接口是包android.widget的私有接口

我是否遗漏了一些东西,或者这看起来像是以某种方式编写的,从而阻止了像这样的行为被定制?他们为什么要费心首先编写一个AbsPosScroller接口


关于如何在不必从头开始编写整个ListView类的情况下获得所需行为的任何线索?

虽然我仍然不知道为什么他们会以一种方式编写这些组件,使其行为无法轻松定制,而这样做非常容易,但我提出了smoothScrollToPos的另一种实现ition(下面代码中的awesomeScrollToPosition)实现了我所需要的功能

该解决方案利用OverScroller对象(内部使用ViscousInterpolator,除非指定了不同的对象)提供我想要的效果,以便滚动到可见页面中的元素(实现跨页面滚动的解决方案更复杂,但这适用于我需要解决的问题)

我基本上实现了一个可运行类,它是我自己的ListView子类(MyListView)的私有类,用于处理滚动动画,只要动画需要运行,就将自己重新发布到UI线程,在每一帧中使用scrollingListBy(但此方法仅在KitKat[19]之后才可用)

公共类MyListView扩展了ListView{
私人迈斯克罗尔;
/*这里是MyListView构造函数*/
公共无效位置(整数位置,整数持续时间){
如果(getChildCount()==0){
//没有子项无法滚动(可见列表项)
回来
}
如果(mScroller==null){
mScroller=new MyScroller();
}
if(mScroller.isRunning()){
msc.停止();
}
int firstPos=getFirstVisiblePosition();
int lastPos=getLastVisiblePosition();
if(!(firstPos)
public class MyListView extends ListView {

    private MyScroller mScroller;

    /* MyListView constructors here */

    public void awesomeScrollToPosition(int position, int duration) {

        if (getChildCount() == 0) {
            // Can't scroll without children (visible list items)
            return;
        }

        if (mScroller == null) {
            mScroller = new MyScroller();
        }

        if (mScroller.isRunning()) {
            mScroller.stop();
        }

        int firstPos = getFirstVisiblePosition();
        int lastPos = getLastVisiblePosition();

        if (!(firstPos <= position && position <= lastPos)) {
            // Can't scroll to an item outside of the visible range this easily
            return;
        }

        int targetPosition = position - firstPos;
        int targetTop = getChildAt(targetPosition).getTop();

        mScroller.start(targetTop, duration);
    }

    private class MyScroller implements Runnable {

        OverScroller mScroller;

        boolean mRunning;
        int mLastY;

        MyScroller() {
            mScroller = new OverScroller(getContext());
            mRunning = false;
        }

        void start(int y, int duration) {

            // start scrolling
            mLastY = 0;
            mScroller.startScroll(0, 0, 0, y, duration);

            mRunning = true;
            postOnAnimation(this);
        }

        boolean isRunning() {
           return mRunning;
        }

        @Override
        public void run() {

            boolean more = mScroller.computeScrollOffset();
            final int currentY = mScroller.getCurrY();

            // actual scrolling
            scrollListBy(currentY - mLastY);

            if (more) {
                mLastY = currentY;

                // schedule next run
                postOnAnimation(this);
            } else {
                stop();
            }
        }

        public void stop() {

            mRunning = false;
            removeCallbacks(this);
        }
    }
}