公司让我把源码settings中的listview具有弹簧效果,类似魅族的那种,可以上下滑动。查了资料,发现:
1.可以在listview的父类abslistview中重写一个回调方法
OverScrollBy(),但是效果是只有listview超过屏幕时才会有弹簧效果,如果listview只有3,4个item是没有效果的。
2.在listviewh中重写OntouchEvent(),在这个方法中通过计算和scrollTo()来达到弹簧效果。但是这种方法会与点击事件冲突。
3.在abslistview中重写OntouchEvent(),也是会有冲突
4.自定义一个listview,重写ontouchEvent(),可以实现。将framworks中的perence里的一些相关布局中的listview改成自定义的,那里用到就在那里改。这也算是这种方法的缺点。如果要让整个系统中的listview都实现弹簧效果,这种方法是不可取的。只能分析源码,解决冲突了。可能是我天生愚钝或者水平不高,看源码对我来说有点困难。这是我接下来要克服和适应的地方。
代码:
package android.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ListView;
public class MyListView extends ListView implements Runnable{
private float mLastDownY = 0f;
private int mDistance = 0; // 手指/弹簧拉去移动的距离
private int mStep = 10;
private boolean mPositive = false; // 滚动方向
public MyListView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public MyListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch(ev.getAction()){
case MotionEvent.ACTION_DOWN:
if(getFirstVisiblePosition()==0||getLastVisiblePosition()==getCount()-1){
mLastDownY = ev.getY();
return true;
}
mDistance =0;
break;
case MotionEvent.ACTION_MOVE:
mDistance=(int)(mLastDownY-ev.getY());
if((mDistance<0&&(getFirstVisiblePosition()==0))||(mDistance>0&&(getLastVisiblePosition()==getCount()-1))){
mDistance/=2;
scrollTo(0, mDistance);
return true;
}
mDistance = 0;
break;
case MotionEvent.ACTION_UP:
if ((mDistance < 0 && getFirstVisiblePosition() == 0)
|| (mDistance > 0 && getLastVisiblePosition() == getCount() - 1)) {
mStep = 1;
mPositive = (mDistance >= 0);
this.post(this); // 启动子线程,用于 "弹回" 效果
return true;
}
mDistance = 0;
break;
}
return super.onTouchEvent(ev);
}
@Override
public void run() {
mDistance += mDistance > 0 ? -mStep : mStep;
scrollTo(0, mDistance);
if ((mPositive && mDistance <= 0) || (!mPositive && mDistance >= 0)) {
scrollTo(0, 0);
mDistance = 0;
mLastDownY = 0f;
return;
}
mStep += 5;
this.postDelayed(this, 10);
}
}