我想过一些不那么优雅的方法来解决这个问题,但我知道我一定遗漏了什么。

我的onItemSelected立即启动,没有与用户进行任何交互,这是不希望的行为。我希望UI能够等到用户选择某样东西后再执行任何操作。

我甚至尝试在onResume()中设置监听器,希望能有所帮助,但它没有。

我怎样才能阻止它在用户可以触摸控件之前发射?

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.
    }
}
}

当前回答

只是为了补充使用onTouchListener来区分对setOnItemSelectedListener的自动调用(这是Activity初始化的一部分,等等)与实际用户交互触发的对它的调用之间的提示,在尝试了其他一些建议后,我做了以下工作,并发现它用最少的代码行就能很好地工作。

只需要为你的Activity/Fragment设置一个布尔字段:

private Boolean spinnerTouched = false;

然后在你设置你的旋转器的setOnItemSelectedListener之前,设置一个onTouchListener:

    spinner.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            System.out.println("Real touch felt.");
            spinnerTouched = true;
            return false;
        }
    });

    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    ...
         if (spinnerTouched){
         //Do the stuff you only want triggered by real user interaction.
        }
        spinnerTouched = false;

其他回答

我用最简单的方法做到了:

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

这也不是一个优雅的解决方案。事实上,这有点像鲁布-戈德堡,但似乎很有效。通过扩展数组适配器并覆盖其getDropDownView,我确保旋转器至少被使用过一次。在新的getDropDownView方法中,我有一个布尔标志,被设置为显示下拉菜单至少被使用过一次。在设置标志之前,我会忽略对侦听器的调用。

MainActivity.onCreate ():

ActionBar ab = getActionBar();
ab.setDisplayShowTitleEnabled(false);
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
ab.setListNavigationCallbacks(null, null);

ArrayList<String> abList = new ArrayList<String>();
abList.add("line 1");
...

ArAd  abAdapt = new ArAd (this
   , android.R.layout.simple_list_item_1
   , android.R.id.text1, abList);
ab.setListNavigationCallbacks(abAdapt, MainActivity.this);

覆盖的数组适配器:

private static boolean viewed = false;
private class ArAd extends ArrayAdapter<String> {
    private ArAd(Activity a
            , int layoutId, int resId, ArrayList<String> list) {
        super(a, layoutId, resId, list);
        viewed = false;
    }
    @Override
    public View getDropDownView(int position, View convertView,
            ViewGroup parent) {
        viewed = true;
        return super.getDropDownView(position, convertView, parent);
    }
}

修改监听器:

@Override
public boolean onNavigationItemSelected(
   int itemPosition, long itemId) {
   if (viewed) {
     ...
   }
   return false;
}

只是为了补充使用onTouchListener来区分对setOnItemSelectedListener的自动调用(这是Activity初始化的一部分,等等)与实际用户交互触发的对它的调用之间的提示,在尝试了其他一些建议后,我做了以下工作,并发现它用最少的代码行就能很好地工作。

只需要为你的Activity/Fragment设置一个布尔字段:

private Boolean spinnerTouched = false;

然后在你设置你的旋转器的setOnItemSelectedListener之前,设置一个onTouchListener:

    spinner.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            System.out.println("Real touch felt.");
            spinnerTouched = true;
            return false;
        }
    });

    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    ...
         if (spinnerTouched){
         //Do the stuff you only want triggered by real user interaction.
        }
        spinnerTouched = false;

我也遇到过类似的情况,我有一个简单的解决办法。

看起来setSelection(int position)和setSelected(int position, boolean animate)方法有不同的内部实现。

当你使用第二个方法setSelected(int position, boolean animate)并带有false animate标志时,你得到的选择不会触发onItemSelected监听器。

spinner.setSelection(Adapter.NO_SELECTION, false);