如何防止 Android ImageView 的点击穿透?

30

我在RelativeLayout中有一个重叠的ImageView,希望防止任何点击事件穿透到它后面的按钮等(从而实际上禁用整个RelativeLayout)。

除了我目前正在使用的迭代RelativeLayout视图并将它们设置为禁用的代码之外,是否有更简单的方法来完成这个任务?

RelativeLayout rlTest = (RelativeLayout ) findViewById(R.id.rlTest);
for (int i = 0; i < rlTest.getChildCount(); i++) {
       View view = rlTest.getChildAt(i);
       view.setEnabled(true);
}

这个回答解决了你的问题吗? [Android:如何防止将触摸事件从一个视图传递到其下面的视图?] (https://dev59.com/YGoy5IYBdhLWcg3wnPWJ) - Top-Master
9个回答

53

你可以设置图像为

android:clickable="true"

7
很遗憾,这不是处理Talkback模式时的理想解决方案。尽管视图没有连接任何东西,但Talkback会宣布其为可点击。 - Mr.Lee
只有在下层视图不是按钮时才有效。否则,按钮仍会捕获点击事件。 - yongsunCN

23

只需调用 rlTest.setClickable(false)。这将防止单击事件传播到子元素。


谢谢您的回答,子视图仍然会接收到点击/轻触事件,我需要同时删除“click”(TapListener)的处理程序吗? - Apqu
啊,太棒了,谢谢,这解决了问题。我猜这比迭代所有视图要少得多的资源密集型! - Apqu
但重新设置setOnClickListener会使其可点击! - Muhammad Babar

17

有一种更加简洁的方法

你可以使用:

android:onClick="preventClicks"

在XML和活动中

public void preventClicks(View view) {}

这适用于片段。 在此 Activity 中的示例有多个重叠的片段,只需在片段的背景中添加 XML 属性,它仍将调用 Activity.preventClicks 并防止触摸其后面的片段


10

以下解决方案适用于一般情况:

_container.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // NOTE: This prevents the touches from propagating through the view and incorrectly invoking the button behind it
        return true;
    }
});

它基本上通过将触摸事件标记为已处理来阻止任何触摸向视图传播。这适用于UI控件和布局容器(例如:LinearLayout,FrameLayout等)。

"clickable"属性设置为false的解决方案对我在代码中或视图XML中使用于布局容器时都无效。


不要这样做。因为我发现这种方式存在BUG,会导致ACTION_UP MotionEvent丢失。 - 林奕忠

2

只需添加这两个监听器:

    // Set an OnTouchListener to always return true for onTouch events so that a touch
    // sequence cannot pass through the item to the item below.
    view.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            v.onTouchEvent(event);
            return true;
        }
    });
    // Set an OnHoverListener to always return true for onHover events so that focus cannot
    // pass through the item to the item below.
    view.setOnHoverListener(new OnHoverListener() {
        @Override
        public boolean onHover(View v, MotionEvent event) {
            v.onHoverEvent(event);
            return true;
        }
    });

2
我假设你正在使用onClickListeners。
那么,使用onTouchListener代替onClickListeners如何?这样做可以让你控制触摸事件在层级结构中的传递深度。例如,如果你在一个相对布局(RL)和一个图像视图(IV)(包含在RL中)上设置了触摸监听器,并分别为它们指定了触摸监听器。现在,如果你从IV的触摸事件中返回true,则RL这个下层成员不会收到触摸事件。但是,如果你从IV的触摸事件中返回false,那么RL这个下层成员将会收到触摸事件。
希望这能帮到你!

0

你也可以将根点击监听器设置为null:

// Do not process clicks on other areas of this fragment
        binding.root.setOnClickListener(null)

这个百分百有效。 它不影响已设置在片段视图上的其他监听器。

0
你可以使用数据绑定并像这样消耗点击事件:
android:onClick="@{() -> true}"

-1
在C#中,我使用一个空委托:
objectName.Click += delegate {};

我还没有遇到它的任何问题,但它确实阻止了点击事件传递到底层控件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接