有個需求,ListView列表支持篩選。點擊篩選Tabs時候,在Tabs下方彈出FilterCard,遮蓋在ListView列表上層,此時不能滑動Tabs,否則界面好尷尬,只有FilterCard消失時候,列表纔回復滑動。已知Tabs是listView的一個HeaderView。要求Tabs支持點擊切換,但是不能上下滑動,此刻要做的就是監聽FilterCard的可見性,VISIBLE時候禁止上下滑動,否則支持滑動。
我們可以設置listView.setEnable(false);但是代價就是連Tabs也不支持點擊了。我們需要的僅僅是禁止其上下滑動。事件分發監控ACTION_MOVE纔是解決問題的根本思路。我們知道, 點擊事件都能通過觸摸後移動來取消這個事件,我們重寫dispatchTouchEvent()時候,一定要保證該體驗不能丟失。
代碼實現如下:
/**
* Created by iblade.Wang on 2019/2/13 14:54
* 該ListView,可以通過setScrollEnable()設置listView是否支持上下滑動
*/
public class ScrollListView extends ListView {
public ScrollListView(Context context) {
super(context);
}
public ScrollListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScrollListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private boolean mIsScroll = true;
/**
* 是否支持上下滑動
*
* @param isScroll 滑動與否
*/
public void setScrollEnable(boolean isScroll) {
mIsScroll = isScroll;
}
private int mPosition;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK;
if (actionMasked == MotionEvent.ACTION_MOVE && !mIsScroll) {
return true;
}
if (actionMasked == MotionEvent.ACTION_DOWN) {
// 記錄手指按下時的位置
mPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
return super.dispatchTouchEvent(ev);
}
// 手指擡起時
if (actionMasked == MotionEvent.ACTION_UP
|| actionMasked == MotionEvent.ACTION_CANCEL) {
// 手指按下與擡起都在同一個視圖內,交給父控件處理,這是一個點擊事件
if (pointToPosition((int) ev.getX(), (int) ev.getY()) == mPosition) {
super.dispatchTouchEvent(ev);
} else {
// 如果手指已經移出按下時的Item,說明是滾動行爲,清理Item pressed狀態, 點擊事件都能通過觸摸後移動來取消這個事件
setPressed(false);
invalidate();
return true;
}
}
return super.dispatchTouchEvent(ev);
}
}