How to keep onItemSelected from firing off on a ne

2019-01-01 07:56发布

I've thought of some less than elegant ways to solve this, but I know I must be missing something.

My onItemSelected fires off immediately without any interaction with the user, and this is undesired behavior. I wish for the UI to wait until the user selects something before it does anything.

I even tried setting up the listener in the onResume(), hoping that would help, but it doesn't.

How can I stop this from firing off before the user can touch the control?

public class CMSHome extends Activity { 

private Spinner spinner;

@Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // Heres my spinner ///////////////////////////////////////////
    spinner = (Spinner) findViewById(R.id.spinner);
    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
            this, R.array.pm_list, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);
    };

public void onResume() {
    super.onResume();
    spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
}

    public class MyOnItemSelectedListener implements OnItemSelectedListener {

    public void onItemSelected(AdapterView<?> parent,
        View view, int pos, long id) {

     Intent i = new Intent(CMSHome.this, ListProjects.class);
     i.putExtra("bEmpID", parent.getItemAtPosition(pos).toString());
        startActivity(i);

        Toast.makeText(parent.getContext(), "The pm is " +
          parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
    }

    public void onNothingSelected(AdapterView parent) {
      // Do nothing.
    }
}
}

30条回答
梦该遗忘
2楼-- · 2019-01-01 08:19

Since nothing worked for me, and I have more than 1 spinner in my view (and IMHO holding a bool map is an overkill) I use the tag to count the clicks :

spinner.setTag(0);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            Integer selections = (Integer) parent.getTag();
            if (selections > 0) {
                // real selection
            }
            parent.setTag(++selections); // (or even just '1')
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });
查看更多
十年一品温如言
3楼-- · 2019-01-01 08:22

The use of Runnables is completely incorrect.

Use setSelection(position, false); in the initial selection before setOnItemSelectedListener(listener)

This way you set your selection with no animation which causes the on item selected listener to be called. But the listener is null so nothing is run. Then your listener is assigned.

So follow this exact sequence:

Spinner s = (Spinner)Util.findViewById(view, R.id.sound, R.id.spinner);
s.setAdapter(adapter);
s.setSelection(position, false);
s.setOnItemSelectedListener(listener);
查看更多
其实,你不懂
4楼-- · 2019-01-01 08:22

I have done with simplest way:

private AdapterView.OnItemSelectedListener listener;
private Spinner spinner;

onCreate();

spinner = (Spinner) findViewById(R.id.spinner);

listener = new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {

            Log.i("H - Spinner selected position", position);
        }

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

        }
    };

 spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
            spinner.setOnItemSelectedListener(listener);
        }

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

        }
    });

Done

查看更多
时光乱了年华
5楼-- · 2019-01-01 08:24

if you need to recreate activity on the fly eg: changing themes , a simple flag/counter wont work

use onUserInteraction() function to detect user activity,

reference : https://stackoverflow.com/a/25070696/4772917

查看更多
不再属于我。
6楼-- · 2019-01-01 08:26

I have had LOTS of issues with the spinner firing of when I didn't want to, and all the answers here are unreliable. They work - but only sometimes. You will eventually run into scenarios where they will fail and introduce bugs into your code.

What worked for me was to store the last selected index in a variable and evaluate it in the listener. If it is the same as the new selected index do nothing and return, else continue with the listener. Do this:

//Declare a int member variable and initialize to 0 (at the top of your class)
private int mLastSpinnerPosition = 0;

//then evaluate it in your listener
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {

  if(mLastSpinnerPosition == i){
        return; //do nothing
  }

  mLastSpinnerPosition = i;
  //do the rest of your code now

}

Trust me when I say this, this is by far the most reliable solution. A hack, but it works!

查看更多
弹指情弦暗扣
7楼-- · 2019-01-01 08:27

My small contribution is a variation on some of the above that has suited me a few times.

Declare an integer variable as a default value (or last used value saved in preferences). Use spinner.setSelection(myDefault) to set that value before the listener is registered. In the onItemSelected check whether the new spinner value equals the value you assigned before running any further code.

This has the added advantage of not running code if the user selects the same value again.

查看更多
登录 后发表回答