Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

On Android, is there any way to disable a Spinner's long-press behavior?

The default spinner behavior is that when it's "closed", longpressing on it will "open" it and show you the dropdown view. I find this behavior to be potentially very problematic for the user. For example, if they're trying to scroll something on the screen, and happen to "grab" a spot that has a spinner, then instead of scrolling, it'll open the dropdown view after a second or so, and the user is basically left with their finger on one of the dropdown options (which they can now accidentally press).

So, I'd like to disable that long-press behavior, and have the spinner "open" when only it's clicked, and not long-pressed. Is that possible?

like image 434
user496854 Avatar asked Jan 13 '15 13:01

user496854


2 Answers

If you only need to restore the standard click behaviour, this is a simpler and more compact version of Jordi's answer:

spinner.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                v.performClick();
            }
            return true;
        }
    });

Further thoughts

This behaviour has also been annoying me. After investigation, it seems like it has a name: drag to open. You can see how it's defined in the source of the AppCompatSpinner#onTouchEvent() method.

Some problems I see with this forced behaviour (and the reason for which some people want to disable it):

  1. It allows the user to selects disabled values in the spinner. By long-pressing, dragging and releasing, you can select values which would not even be selectable with a normal interaction (click-to-open + click-to-select)
  2. As a consequence of #1, it can also make Espresso test fail very easily. Indeed, in Espresso, the duration of a click is rather unstable and one tap can quickly turn into a long-press-and-select-interaction.
  3. Finally, the biggest problem here is that there is no method / XML attribute to disable the "drag to open" behaviour...

Let's have it fixed!

I've opened a ticket related to this on the AOSP issue tracker: #228953. Feel free to follow it, or to comment if I missed anything.

like image 102
David Ferrand Avatar answered Sep 20 '22 12:09

David Ferrand


So, I've figured out a relatively easy way to do this, even though it's not very elegant. Basically, I created a transparent overlay view on top of the Spinner, and set it to have an OnClickListener that just triggers a Spinner's click.

XML:

    <Spinner 
        android:id="@+id/spinner"
        android:layout_width="match_parent" 
        android:layout_height="40dip" />

    <View android:id="@+id/spinner_overlay"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:layout_alignLeft="@id/spinner" 
        android:layout_alignRight="@id/spinner"
        android:layout_alignTop="@id/spinner" 
        android:layout_alignBottom="@id/spinner"  />

Java:

        View spinnerOverlay = findViewById(R.id.spinner_overlay);
        spinnerOverlay.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                spinner.performClick();
            }

        });
like image 23
user496854 Avatar answered Sep 20 '22 12:09

user496854