Java 修改ListView';s平滑拓扑变换
调用smoothScrollToPosition时,ListView的默认行为是以线性速度移动到指定位置 深入研究ListView和AbsListView的代码,我可以看到发生这种行为是因为AbsListView使用一个定位器滚动器对象(实现AbsPositionScroller),该对象反过来使用一个FlingRunnable对象,在该对象上使用linear=true调用startScroll方法(最终使其OverScroller对象使用LinearInterpolator) 我想修改这个行为,让它使用OverScroller类默认使用的Scroller.ViscousFluidInterpolator类,但我没有找到一种方法 我看到AblistView定义了一个AbsPosScroller接口(他自己用一个PositionScroller类实现),我可以尝试用我自己的类来实现它,最终使用ViscousFluidInterpolator,但由于某些原因,这个接口是包android.widget的私有接口 我是否遗漏了一些东西,或者这看起来像是以某种方式编写的,从而阻止了像这样的行为被定制?他们为什么要费心首先编写一个AbsPosScroller接口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) 我想修改这个行为
关于如何在不必从头开始编写整个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);
}
}
}