如何针对特定布局使用dispatchTouchEvent控制触摸事件?
针对特定布局启用/禁用触摸事件的解决方案
嘿,这个问题我做项目时也碰到过!直接在Activity的dispatchTouchEvent里返回true确实会全局锁死触摸,咱们换个思路,直接在目标布局本身上处理就精准多了,给你几个实用的方案:
方案1:给禁用触摸的布局设置触摸监听器(最简单)
直接给你想禁用触摸的布局绑定一个OnTouchListener,在回调里返回true——这样该布局及其所有子View都会被屏蔽触摸事件,其他布局不受任何影响:
// 在Activity的onCreate里获取目标布局实例 View disableTouchLayout = findViewById(R.id.layout_need_disable); disableTouchLayout.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // 返回true表示"我已经处理了这个触摸事件",不会再往下传递 return true; } });
方案2:自定义禁用触摸的布局类(适合重复使用)
如果这个禁用触摸的布局你在多个页面都要用,不如封装成自定义布局,一劳永逸:
public class NoTouchLayout extends LinearLayout { // 记得实现所有必要的构造方法 public NoTouchLayout(Context context) { super(context); } public NoTouchLayout(Context context, AttributeSet attrs) { super(context, attrs); } public NoTouchLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { // 直接消费所有触摸事件,阻止传递给子View和自身的触摸回调 return true; } }
然后在XML布局文件里直接用这个自定义类代替原来的布局标签就行:
<com.yourpackage.NoTouchLayout android:id="@+id/layout_need_disable" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 子View内容 --> </com.yourpackage.NoTouchLayout>
方案3:仅允许指定布局响应触摸(全局过滤)
如果你的需求反过来:只有某个布局能触摸,Activity其他区域都禁用,那可以在Activity的dispatchTouchEvent里判断触摸点的位置,精准过滤:
private View enableTouchLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); enableTouchLayout = findViewById(R.id.layout_need_enable); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { // 获取触摸点的屏幕绝对坐标 int touchX = (int) ev.getRawX(); int touchY = (int) ev.getRawY(); // 获取允许触摸的布局在屏幕上的位置范围 Rect layoutRect = new Rect(); enableTouchLayout.getGlobalVisibleRect(layoutRect); if (layoutRect.contains(touchX, touchY)) { // 触摸点在目标布局内,让事件正常传递处理 return super.dispatchTouchEvent(ev); } else { // 触摸点在外部,消费事件,禁用触摸 return true; } }
小提醒
- 如果禁用触摸的布局有子View,方案1和2都能有效屏蔽子View的触摸,因为触摸事件会被父布局优先消费。
- 要是你只是想禁用布局的点击(而非所有触摸,比如长按、滑动),可以用
setClickable(false)+setLongClickable(false),但这种方式不会屏蔽子View的触摸哦~
内容的提问来源于stack exchange,提问作者Ragul Murugan
相关产品推荐
相关产品推荐

