233

I have an object where the text cycles and displays status messages. When the messages change, I want the click event of the object to change to take you to the activity that the message is relating to.

So, I have a TextView mTitleView and I'm assigning the event like this.

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

How do I remove that click event? There are some status messages that do not have an actionable area so I'd like to turn off the click event. I'd also like to be able to cycle through these click events and dispose of them properly, but I'm unsure of the best practice.

Josh
  • 16,286
  • 25
  • 113
  • 158

10 Answers10

490

mTitleView.setOnClickListener(null) should do the trick.

A better design might be to do a check of the status in the OnClickListener and then determine whether or not the click should do something vs adding and clearing click listeners.

Robby Pond
  • 73,164
  • 16
  • 126
  • 119
  • 1
    There isn't any other cleanup I have to do to deregister the event? – Josh Mar 04 '11 at 15:02
  • 2
    Nope. The listener is just an object that the view uses to call a method when you click so when you set it to null it destroys it. – Robby Pond Mar 04 '11 at 15:04
  • 21
    i wonder if listeners cause memory allocation ? Do we need to free them ? Will that raise performance of app ? – alicanbatur Nov 04 '13 at 11:42
  • What can we do to remove onCompletionListener() in MediaPlayer ? Setting it as "null" is throwing NullPointerException. – Ankit Bansal Nov 30 '14 at 10:38
  • 2
    Thanks for your answer, mind adding why do you think that checking status or a flag in the listener is better. – kapv89 Oct 29 '15 at 18:56
  • 2
    When you say `a better design` are you implying performance implications or are you just saying it's a bit distasteful? – RTF Mar 25 '16 at 20:22
  • If there are more than one `OnClickListener`s registered on a view, will calling `setOnClickListener(null)` on a particular `view`, remove all of them? – CLOUGH Aug 06 '16 at 15:24
  • 1
    If you want the view to be "transparent" to the click you do have to use @FreewhelNat suggestion. Otherwise underlying views will not get the touch messages – Cortex Jan 01 '17 at 15:43
  • Wont this remove all click listeners? Isn't there a better method? – Sreekanth Karumanaghat Oct 30 '17 at 02:39
  • No worries about memory allocation. Setting null will clear a strong reference, and Garbage Collector would destroy listener instances. – Michał Dobi Dobrzański Aug 31 '18 at 11:14
  • Even if setting `null` listener, a view with property `android:background="?attr/selectableItemBackground"` is still going to trigger the ripple effect. So, instead of `null` listener, I apply `setClickable(false)`. – Starwave Jun 05 '20 at 12:53
156

Note that if a view is non-clickable (a TextView for example), setting setOnClickListener(null) will mean the view is clickable. Use mMyView.setClickable(false) if you don't want your view to be clickable. For example, if you use a xml drawable for the background, which shows different colours for different states, if your view is still clickable, users can click on it and the different background colour will show, which may look weird.

FreewheelNat
  • 2,907
  • 1
  • 20
  • 12
  • This is good to know for TextView's and such, but for a ListView it has no effect when a OnClickListener was previously set. – Someone Somewhere Feb 03 '13 at 00:59
  • 5
    This is why I wrote "Note that if a view is non-clickable (a TextView for example)" - a ListView is clickable and so this doesn't work for it. – FreewheelNat Feb 12 '13 at 17:34
  • If we need to switch back and forth to disable/enable the View's onClickListener, in my opinion, this is the better solution than setting setOnClickListener(null). – Panini Luncher Oct 08 '14 at 20:13
  • 2
    view.setOnClickListener(null) together with view.setClickable(false) is the correct answer, thanks!!!! – Petros Mastrantonas May 13 '15 at 19:30
  • Remember that you need to call first set listener null then clickable false. Open setOnClickListener implementation and you will see it calls setClickable(true) – Ultimo_m Aug 05 '21 at 14:06
13

Perhaps setOnClickListener(null) ?

Luther
  • 1,786
  • 3
  • 21
  • 38
  • 2
    This doesn't work for checkboxes specifically, and will likely not work for other widgets as well. – Chris May 21 '15 at 20:08
11

Setting setOnClickListener(null) is a good idea to remove click listener at runtime.

And also someone commented that calling View.hasOnClickListeners() after this will return true, NO my friend.

Here is the implementation of hasOnClickListeners() taken from android.view.View class

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

Thank GOD. It checks for null.

So everything is safe. Enjoy :-)

Azim Ansari
  • 1,378
  • 11
  • 20
6

You could add the following extension function:

fun View.removeClickListener() {
  setOnClickListener(null)
  isClickable = false
}

And then on your callers you'd do:

val textView = findViewById(R.id.activity_text)
textView.removeClickListener()
Evin1_
  • 12,292
  • 9
  • 45
  • 47
5

The above answers seem flighty and unreliable. I tried doing this with an ImageView in a simple Relative Layout and it did not disable the onClick event.

What did work for me was using setEnabled.

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

You can then check whether the View is enabled with:

boolean ImageView.isEnabled();

Another option is to use setContentDescription(String string) and String getContentDescription() to determine the status of a view.

4

Just put,it has worked for me

itemView.setOnClickListener(null);
saigopi.me
  • 14,011
  • 2
  • 83
  • 54
  • Won't be enough in some edge cases, you may still get cliks if for example tapping really fast, etc. – David Mar 25 '22 at 04:04
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();
        }

    }
}
androidmalin
  • 899
  • 1
  • 8
  • 12
2

Using Kotlin as

view.setOnClickListener { null }
view.isClickable = false
Thiago
  • 12,778
  • 14
  • 93
  • 110
-1

Just reinitializing item as below would do the trick. It would remove onclick,onlonglick,onitemclick,onitemlongclick based on item

mTitleView = findViewById(R.id.mTitleView);

Rockit Rockit
  • 146
  • 1
  • 5