Android的ListView/ScrollView支持回弹效果
看到iOS里面的Table和ScrollView都能在拉到头的时候,还能继续滑出来,松手就弹回去,感觉确实很爽。但是Android上默认是没有这个效果的,很多第三方rom或者app都支持这种效果。
搜索了一下才发现这篇博客,原来Android2.3中就支持overscroll功能。但是实现机制和iOS不一样,可能是专利的问题。Android上实现很简单,如果拉到底了,就会在边上出现发光效果。我们可以很容易修改,达到像iOS上面那样的效果。代码如下:
public class BounceListView extends ListView{
private static final int MAX_Y_OVERSCROLL_DISTANCE = 200;
private Context mContext;
private int mMaxYOverscrollDistance;
public BounceListView(Context context){
super(context);
mContext = context;
initBounceListView();
}
public BounceListView(Context context, AttributeSet attrs){
super(context, attrs);
mContext = context;
initBounceListView();
}
public BounceListView(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
mContext = context;
initBounceListView();
}
private void initBounceListView(){
//get the density of the screen and do some maths with it on the max overscroll distance
//variable so that you get similar behaviors no matter what the screen size
final DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
final float density = metrics.density;
mMaxYOverscrollDistance = (int) (density * MAX_Y_OVERSCROLL_DISTANCE);
}
@Override
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent){
//This is where the magic happens, we have replaced the incoming maxOverScrollY with our own custom variable mMaxYOverscrollDistance;
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, mMaxYOverscrollDistance, isTouchEvent);
}
}
这里的关键是重载了方法overScrollBy()
,传入一个之mMaxYOverscrollDistance。默认是0,所以拉到头就拉不动了。
上面的效果已经接近iOS上的效果了,但是看体验起来开始有点生硬,我们加入一些摩擦里,获得更好的体验,修改overScrollBy()
方法如下:
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX,
int scrollY, int scrollRangeX, int scrollRangeY,
int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
if (!isTouchEvent) { // 禁止惯性滑动
if ((scrollY < 0 && deltaX < 0)
|| (scrollY > getHeight() && deltaX > 0)) {
deltaY = 0;
}
}
return super.overScrollBy(deltaX, (deltaY + 1) / 2, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, mMaxScroll, isTouchEvent);
}
加入摩擦力就是这里:(deltaY + 1) / 2
。上面那个条件判断,是禁用惯性运动。这样效果就自然多了。