📅  最后修改于: 2023-12-03 15:32:43.551000             🧑  作者: Mango
当我们在开发应用时会使用到ListView来展示数据,但是在默认情况下,当ListView滚动到顶部或底部时会出现拉动飞溅的效果,这不仅影响用户体验,还会影响应用整体的美观度。因此,我们需要禁用ListView的拉动飞溅。下面将介绍具体的实现方法。
推荐使用Android Support Library中的RecyclerView代替ListView。RecyclerView是一个功能更为强大的控件,同时也默认提供了禁用拉动飞溅的功能。如果要使用ListView,可以使用第三方库Android-ObservableScrollView来禁用拉动飞溅。Android-ObservableScrollView是一个可观察的滚动视图库,它提供了多种观察ListView滚动事件的方法,其中包括禁用拉动飞溅的方法。
ObservableListView listView = findViewById(R.id.list_view);
listView.setScrollViewCallbacks(new ObservableScrollViewCallbacks() {
@Override
public void onScrollChanged(int scrollY, boolean firstScroll, boolean dragging) {
// 滚动回调
}
@Override
public void onDownMotionEvent() {
// 手指按下回调
}
@Override
public void onStopNestedScroll() {
// 停止滚动回调
}
@Override
public void onUpOrCancelMotionEvent(ScrollState scrollState) {
// 手指抬起或取消回调
}
@Override
public void onScrollStateChanged(int state) {
// 滚动状态改变回调
}
});
另外一种方法是继承ListView,并重写onTouchEvent方法,在该方法中计算ListView滚动的距离,当滚动到顶部或底部时,将事件拦截,从而禁用拉动飞溅效果。
public class CustomListView extends ListView {
private float mDownY;
private float mMoveY;
private float mLastY;
private int mMaxOverScrollY;
public CustomListView(Context context) {
super(context);
initView();
}
public CustomListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public CustomListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
@SuppressLint("ClickableViewAccessibility")
private void initView() {
mMaxOverScrollY = getContext().getResources().getDimensionPixelSize(R.dimen.listview_overscroll_distance);
setOverScrollMode(OVER_SCROLL_NEVER); // 禁用ListView的拉动飞溅效果
setVerticalScrollBarEnabled(false); // 禁用ListView的垂直滚动条
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownY = event.getRawY();
mLastY = mDownY;
break;
case MotionEvent.ACTION_MOVE:
mMoveY = event.getRawY();
if (mMoveY - mLastY < 0 && getLastVisiblePosition() == getCount() - 1 && Math.abs(mMoveY - mDownY) >= mMaxOverScrollY) {
// 拉动到底部
return true; // 拦截事件
} else if (mMoveY - mLastY > 0 && getFirstVisiblePosition() == 0 && Math.abs(mMoveY - mDownY) >= mMaxOverScrollY) {
// 拉动到顶部
return true; // 拦截事件
}
mLastY = mMoveY;
break;
default:
break;
}
return false;
}
});
}
}
用以上两种方法都可以禁用ListView的拉动飞溅效果,开发者可以根据实际情况进行选择。