Android: 如何防止任何触摸事件从一个视图传递到它下面的视图?

特别是使用下面的代码,是否有办法修改它,使这个新创建的视图下的活动不接收任何手势?

View v1 = new View(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
1000,
50,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.OPAQUE);


params.gravity = Gravity.BOTTOM;
WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
wm.addView(v1, params);
60744 次浏览

向顶部位置的视图添加 onTouchEvent方法,然后返回 true。True 将告诉事件冒泡,该事件已被使用,因此防止事件冒泡到其他视图。

protected boolean onTouchEvent (MotionEvent me) {
return true;
}

对于 v1,你可以做一个导入:

import android.view.View.OnTouchListener;

然后设置 onTouchListener:

v1.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});

从代码

View v1 = new View(this);
v1.setClickable(true);
v1.setFocusable(true);

或者

来自 xml

<View
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="My button"
android:focusable="true"
android:clickable="true"/>

这将防止触摸和单击事件被传播到视图下方的视图。
或者,如果您膨胀了视图,那么在.xml 中添加 android:clickable="true"

你也可以的。可以将触摸监听器设置为子视图,然后在 onTouch()事件中可以阻止父事件的 intercept touch event

也就是说。

View v = findViewById(R.id.sample_view);
v.setOnTouchListener(new OnTouchListener() {
// Setting on Touch Listener for handling the touch inside ScrollView
@Override
public boolean onTouch(View v, MotionEvent event) {
// Disallow the touch request for parent scroll on touch of child view
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});

我有点晚了,但我不认为接受的解决方案是非常伟大的。下面是一个静态方法,它接受任意数量的视图并禁用此事件冒泡。对于 API 17 + (较低的未测试) ,这种方法在我身上100% 奏效

public static void disableEventBubbling(View... views){
for(View view : views){
if(view != null){
view.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(View view, MotionEvent event){
view.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
}
}
}

您可以为任何类型的事件添加一个案例,或者您可以去掉开关,使默认案例成为触摸侦听器内的唯一一行。

你只需要打个电话

arg0.getParent().requestDisallowInterceptTouchEvent(true);

在你的 onTouch 函数开始的时候,像这样

    @Override
public boolean onTouch(View arg0, MotionEvent arg1) {
arg0.getParent().requestDisallowInterceptTouchEvent(true);
switch(arg1.getActio){
}


return false;


}

您可以像下面这样添加一个视图,但要确保它是您添加到 xml 中的最后一个视图。Xml 中的最后一项是位于其下所有其他视图之上的项。

<View
android:id="@+id/blocking_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#AA666666"
android:clickable="true"
android:focusable="true"
android:visibility="visible"/>

只需添加一个点击委托到顶部视图背景,这将停止下面的视图接收触摸

linear_layout_background.Click += delegate
{
// Ensures views underneath does not receive touch events
};

我认为最好的方法是添加一个触摸事件并设置返回值 没错

正如你在这里看到的:

  someView.setOnTouchListener(object: View.OnTouchListener {
override fun onTouch(v: View?, event: MotionEvent?): Boolean{
return true
}


})

返回 True 意味着顶部视图正在处理触摸,而不需要将触摸事件移交给其他相关视图。