Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spinner onItemSelected called erroneously (without user action)

I have a spinner which I am showing in a dialog view, and the moment the dialog starts onItemSelected is called. I don't really want to process this but only when user makes the selection. So I either need to prevent this (maybe because no default value is set?), or I need to know it is not the user that is making this selection?

like image 454
Androider Avatar asked Feb 26 '11 03:02

Androider


5 Answers

Another option in the spirit of Bill Mote's solution is to make the OnItemSelectedListener also an OnTouchListener. The user interaction flag can then be set to true in the onTouch method and reset in onItemSelected() once the selection change has been handled. I prefer this solution because the user interaction flag is handled exclusively for the spinner, and not for other views in the activity that may affect the desired behavior.

In code:

Create your listener for the spinner:

public class SpinnerInteractionListener implements AdapterView.OnItemSelectedListener, View.OnTouchListener {

    boolean userSelect = false;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        userSelect = true;
        return false;
    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
        if (userSelect) { 
            // Your selection handling code here
            userSelect = false;
        }
    }

}

Add the listener to the spinner as both an OnItemSelectedListener and an OnTouchListener:

SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);
like image 89
Andres Q. Avatar answered Nov 14 '22 18:11

Andres Q.


You can simply add an int count to solve it :)

 sp.setOnItemSelectedListener(new OnItemSelectedListener() {
    int count=0;
    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        if(count >= 1){
            int item = sp.getSelectedItemPosition();
            Toast.makeText(getBaseContext(),
                 "You have selected the book: " + androidBooks[item],
                  Toast.LENGTH_SHORT).show();
        }
        count++;
    }


    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
    }
});
like image 35
Günay Gültekin Avatar answered Nov 14 '22 18:11

Günay Gültekin


Beginning with API level 3 you can use onUserInteraction() on an Activity with a boolean to determine if the user is interacting with the device.

http://developer.android.com/reference/android/app/Activity.html#onUserInteraction()

@Override
public void onUserInteraction() {
    super.onUserInteraction();
    userIsInteracting = true;
}

As a field on the Activity I have:

private boolean userIsInteracting;

Finally, my spinner:

    mSpinnerView.setOnItemSelectedListener(new OnItemSelectedListener() {

        @Override
        public void onItemSelected(AdapterView<?> arg0, View view, int position, long arg3) {
            spinnerAdapter.setmPreviousSelectedIndex(position);
            if (userIsInteracting) {
                updateGUI();
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> arg0) {

        }
    });

As you come and go through the activity the boolean is reset to false. Works like a charm.

like image 38
Bill Mote Avatar answered Nov 14 '22 17:11

Bill Mote


Androider, I have found a solution for this problem and posted it here (with code sample):

Spinner onItemSelected() executes when it is not suppose to

like image 6
Someone Somewhere Avatar answered Nov 14 '22 18:11

Someone Somewhere


I have solved this problem a different way as I noticed sometimes the onItemSelected method was called twice on orientation change or sometimes once.

It seemed to depend on the current spinner selection. So a flag or counter didn't work for me. Instead I record the system time in BOTH onResume() and onCreate using widgetsRestartTime = System.currentTimeMillis()

widgetsRestartTime is declared as a double and as an intance variable.

Now in the onItemSelected() method I check the current time again and subtract widgetsRestartTime from it as follows: if (System.currentTimeMillis() - widgetsRestartTime > 200) { // user triggered event - so this is a real spinner event so process it } else { // system generated event e.g. orientation change, activity startup. so ignore }

like image 4
karl Avatar answered Nov 14 '22 16:11

karl