18

I want to capture the onClick event when the user selects a spinner value.

I've tried implementing OnClickListener and using the following code:

@Override
public void onClick(final View view) {
  if (view == countrySpinner) {
    Toast.makeText(this, "Override OK!", 3);
  }
}

And binding with:

countrySpinner.setOnClickListener(this);

This compiles, but I get a RuntimeException advising me to use OnItemClickListener rather than OnClickListener for an AdapterView.

How can I capture that onClick event?

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
tacos_tacos_tacos
  • 10,277
  • 11
  • 73
  • 126
  • `Spinner` does not support click events, as the exception plainly tells you. Either use selection events or do not use a `Spinner`. – CommonsWare Apr 18 '12 at 15:55
  • @CommonsWare, how then would I go about loading Spinner list items from a Web Service without doing it eagerly? Is it just not possible to do this? (Seems like a large limitation!) – tacos_tacos_tacos Apr 18 '12 at 15:56
  • Loading content into a `Spinner` has nothing to do with click events, any more than generating a Web page has anything to do with somebody clicking a link on the page itself once loaded in a browser. I have no idea what you think "eagerly" is. If you have questions on populating a `Spinner`, please open a fresh SO question. – CommonsWare Apr 18 '12 at 16:28
  • As CommonsWare says you don't need to wait until the users clicks your spinner to populate it. You populate it by setting an ArrayAdapter. There are tutorials out there, and one [here](http://developer.android.com/resources/tutorials/views/hello-spinner.html) (although they use local resources to populate the spinner). Just do a webcall to get your spinner items and then create an ArrayAdapter. – Tony Chan Apr 20 '12 at 00:57

3 Answers3

23

Instead of setting the spinner's OnClickListener,try setting OnTouchListener and OnKeyListener.

spinner.setOnTouchListener(spinnerOnTouch);
spinner.setOnKeyListener(spinnerOnKey);

and the listeners:

private View.OnTouchListener spinnerOnTouch = new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            //Your code
        }
        return false;
    }
};
private static View.OnKeyListener spinnerOnKey = new View.OnKeyListener() {
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
            //your code
            return true;
        } else {
            return false;
        }
    }
};
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
ValayPatel
  • 1,094
  • 12
  • 15
  • 3
    Your code will make the `Spinner` completely unusable, by consuming all touch and key events. If that is the objective, the OP should simply use a `Button`. – CommonsWare Apr 18 '12 at 15:55
  • @CommonsWare I hope this will work now... by mistake I return true in onTouchListener. It should be false – ValayPatel Apr 18 '12 at 18:54
  • 2
    I doubt that will help. Chain to the superclass if you want the superclass to have its normal behavior. – CommonsWare Apr 18 '12 at 18:55
  • I checked it and it is working on my end. Spinner is behaving normally – ValayPatel Apr 18 '12 at 19:14
  • 2
    @CommonsWare: this is exactly what I wanted. A `Button` does not _look_ like a spinner. – Violet Giraffe Aug 16 '16 at 11:36
  • @VioletGiraffe: That is why you should not do this. The user will click the `Spinner`, expecting the typical `Spinner` behavior. The user will be confused when your `Spinner` does not behave as expected. – CommonsWare Aug 16 '16 at 11:52
  • @CommonsWare: I understand you and generally agree with that, but in my a case a spinner makes for a cleaner UI even though it doesn't behave exactly like a normal spinner. – Violet Giraffe Aug 16 '16 at 16:24
  • This doesn't work for screenreader users. Any idea how to intercept the talkback onClick event? – Huw Davies Jul 11 '18 at 02:42
  • How about some credit? Your answer was copied and pasted from here: https://stackoverflow.com/questions/3928071/setting-a-spinner-onclicklistener-in-android/8520801#8520801 – OferR Sep 29 '18 at 22:22
  • this solution misses to validate if a touch is a click. E.g. touching the spinner and swipe away from it will be handled like a touch, so ANY touch down on the spinner will be handled as a click, you can't cancel it anymore... – prom85 Jan 11 '19 at 12:11
16

Don't treat a spinner like a button, buttons have onClick events. Spinners have onItemSelected events.

You should be capturing the Spinner's onItemSelected event like this:

import android.widget.AdapterView;

Spinner productname_spinner =(Spinner) findViewById(R.id.your_spinner);

productname_spinner.setOnItemSelectedListener(
    new AdapterView.OnItemSelectedListener() {
    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {

        Object item = parent.getItemAtPosition(pos);
        System.out.println(item.toString());     //prints the text in spinner item.

    }
    public void onNothingSelected(AdapterView<?> parent) {
    }
});

In Kotlin, similar to the following:

mySpinner.onItemSelectedListener = object: OnItemSelectedListener {
    override fun onNothingSelected(parent: AdapterView<*>?) {
        // Do nothing
    }
    override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
        val selection = parent?.getItemAtPosition(position)
        viewModel.updateSelection(selection as String)
    }
}
Anonsage
  • 8,030
  • 5
  • 48
  • 51
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
0

I've tried implementing OnItemSelectedListener to get Selected Spinner Value , using the following code:

String selectAreaNameString;

AreaSpinner.setOnItemSelectedListener(AreaSpinnerSelected = new AdapterView.OnItemSelectedListener() {
        public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {

            Object item = parent.getItemAtPosition(pos);


            selectAreaNameString = item.toString();
});
Pramesh Bhalala
  • 273
  • 1
  • 3
  • 9