移除一个onclick监听器。

234

我有一个对象,其中的文本循环并显示状态消息。当消息更改时,我希望该对象的点击事件更改为将您带到与消息相关联的活动。

因此,我有一个TextView mTitleView,我像这样分配事件。

public void setOnTitleClickListener(OnClickListener listener) {
    mTitleView.setOnClickListener(listener);
}

如何删除点击事件?有一些状态消息没有可操作区域,因此我想关闭点击事件。我还想能够循环遍历这些点击事件并正确地处理它们,但我不确定最佳实践。

10个回答

491

mTitleView.setOnClickListener(null) 可以解决问题。

更好的设计可能是在 OnClickListener 中检查状态,然后确定是否应该执行点击操作,而不是添加和清除点击监听器。


2
不是的。监听器只是一个对象,视图用它来调用方法当你点击时,所以当你将其设置为null时,它就被销毁了。 - Robby Pond
21
听众是否会导致内存分配?我们需要释放它们吗?这样做会提高应用程序的性能吗? - alicanbatur
2
谢谢你的回答,能否再解释一下为什么你认为在监听器中检查状态或标志更好。 - kapv89
2
当你说“更好的设计”时,你是在暗示性能方面的影响,还是只是说它有点不雅观? - RTF
1
如果您希望视图对点击事件“透明”,则确实需要使用@FreewhelNat的建议。否则,底层视图将无法接收到触摸消息。 - Cortex
显示剩余7条评论

156

请注意,如果一个视图是不可点击的(比如一个TextView),设置setOnClickListener(null)将意味着该视图变得可点击。如果您不希望您的视图可点击,请使用mMyView.setClickable(false)。例如,如果您为背景使用了xml drawable,它会根据不同状态显示不同的颜色,如果您的视图仍然是可点击的,用户可以单击它,不同的背景颜色会显示出来,可能会看起来很奇怪。


这对于TextView等控件很有用,但是对于ListView,如果先前设置了OnClickListener,则没有影响。 - Someone Somewhere
5
这就是我写“请注意,如果一个视图是不可点击的(例如 TextView)”的原因——ListView 是可点击的,所以这对它没有作用。 - FreewheelNat
如果我们需要来回切换以禁用/启用视图的onClickListener,我认为这比设置setOnClickListener(null)更好。 - Panini Luncher
2
view.setOnClickListener(null)和view.setClickable(false)是正确的答案,谢谢!!! - Petros Mastrantonas
记得需要先调用 setListener(null),然后再将 clickable 设为 false。打开 setOnClickListener 的实现,你会看到它调用了 setClickable(true)。 - Ultimo_m

13

也许是 setOnClickListener(null)


2
这对复选框不起作用,很可能对其他小部件也不起作用。 - Chris

11

在运行时删除点击监听器的好方法是设置setOnClickListener(null)

有人评论说在此之后调用View.hasOnClickListeners()会返回true,但实际上不会,我的朋友。

这里是从android.view.View类中获取的hasOnClickListeners()的实现方式。

 public boolean hasOnClickListeners() {
        ListenerInfo li = mListenerInfo;
        return (li != null && li.mOnClickListener != null);
    }

谢天谢地,它检查了null

所以一切都很安全。享受吧 :-)


6
您可以添加以下扩展函数:
fun View.removeClickListener() {
  setOnClickListener(null)
  isClickable = false
}

然后在您的调用者中,您需要执行以下操作:

val textView = findViewById(R.id.activity_text)
textView.removeClickListener()

5

以上答案似乎不够可靠。我曾在一个简单的RelativeLayout中使用ImageView尝试过这种方法,但它并没有禁用onClick事件。

对我有用的方法是使用setEnabled。

ImageView v = (ImageView)findViewByID(R.id.layoutV);
v.setEnabled(false);

您可以使用以下代码检查视图是否已启用:

isEnabled = view.isEnabled();

boolean ImageView.isEnabled();

另一个选项是使用setContentDescription(String string)和String getContentDescription()来确定视图的状态。

4
简单来说,这对我很有效。
itemView.setOnClickListener(null);

在某些边缘情况下可能不够用,例如如果快速点击等,仍然可能会得到点击。 - David

3
    /**
 * Remove an onclick listener
 *
 * @param view
 * @author malin.myemail@gmail.com
 * @website https://github.com/androidmalin
 * @data 2016-05-16
 */
public static void unBingListener(View view) {
    if (view != null) {
        try {
            if (view.hasOnClickListeners()) {
                view.setOnClickListener(null);

            }

            if (view.getOnFocusChangeListener() != null) {
                view.setOnFocusChangeListener(null);

            }

            if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
                ViewGroup viewGroup = (ViewGroup) view;
                int viewGroupChildCount = viewGroup.getChildCount();
                for (int i = 0; i < viewGroupChildCount; i++) {
                    unBingListener(viewGroup.getChildAt(i));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

2

使用Kotlin作为

view.setOnClickListener { null }
view.isClickable = false

-1

只需按照以下方式重新初始化项目即可解决问题。它将基于项目删除 onclick、onlonglick、onitemclick 和 onitemlongclick。

mTitleView = findViewById(R.id.mTitleView);


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