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

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

当前回答

布尔标志或计数器的解决方案没有帮助我,因为在方向变化onItemSelected()调用“飞越”标志或计数器。

我子类化了android.widget.Spinner,并做了一些小的补充。相关部分如下。这个解决方案对我很有效。

private void setHandleOnItemSelected()
{
  final StackTraceElement [] elements = Thread.currentThread().getStackTrace();

  for (int index = 1; index < elements.length; index++)
  {
     handleOnItemSelected = elements[index].toString().indexOf("PerformClick") != -1; //$NON-NLS-1$

     if (handleOnItemSelected)
     {
        break;
     }
  }
}

@Override
public void setSelection(int position, boolean animate)
{
  super.setSelection(position, animate);

  setHandleOnItemSelected();
}

@Override
public void setSelection(int position)
{
  super.setSelection(position);

  setHandleOnItemSelected();
}

public boolean shouldHandleOnItemSelected()
{
  return handleOnItemSelected;
}

其他回答

我创建了一个小工具方法来改变Spinner选择而不通知用户:

private void setSpinnerSelectionWithoutCallingListener(final Spinner spinner, final int selection) {
    final OnItemSelectedListener l = spinner.getOnItemSelectedListener();
    spinner.setOnItemSelectedListener(null);
    spinner.post(new Runnable() {
        @Override
        public void run() {
            spinner.setSelection(selection);
            spinner.post(new Runnable() {
                @Override
                public void run() {
                    spinner.setOnItemSelectedListener(l);
                }
            });
        }
    });
}

它禁用侦听器,更改选择,然后重新启用侦听器。

诀窍是调用对UI线程是异步的,所以必须在连续的处理程序中执行。

如果你需要在飞行中重新创建活动,例如:改变主题,一个简单的标志/计数器不会工作

使用onUserInteraction()函数检测用户活动,

参考资料:https://stackoverflow.com/a/25070696/4772917

我需要在ViewHolder中使用mSpinner,因此标记mOldPosition在匿名内部类中设置。

mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            int mOldPosition = mSpinner.getSelectedItemPosition();

            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long l) {
                if (mOldPosition != position) {
                    mOldPosition = position;
                    //Do something
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {
                //Do something
            }
        });

设计一种通用的转轮,只需数据输入,由用户选择,优点: 1. 保持旋转样式相同的应用程序。 2. 在任何地方启动旋转器。 3.易于处理链接转轮(重新启动ReuseSpinner与不同的数据)。

我的演示示例:ReuseSpinner 传递数据到ReuseSpinner:

Intent intent = new Intent(MainActivity.this, SpinnerActivity.class);
intent.putExtra(SpinnerActivity.Extra_Resource, arrayList);
startActivityForResult(intent, mRequestCode_select_country_prompt);

获取用户选择:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);

        if(requestCode == mRequestCode_select_country && resultCode == RESULT_OK){
            if(data != null){
                Map.Entry<String,String> entry = (Map.Entry<String,String>) data.getSerializableExtra(SpinnerActivity.Result_Data);
                if(entry != null){
                    Log.i(TAG, String.format("get result -> key:%s , value:%s", entry.getKey(), entry.getValue()));

                }
            }
        }
    }

我可能在帖子上回答得太迟了,但是我设法实现了这一点,使用Android数据绑定库Android Databinding。我创建了一个自定义绑定,以确保监听器不被调用,直到选定的项目被改变,所以即使用户选择相同的位置,一遍又一遍地事件不会被触发。

布局xml文件

    <layout>
  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_vertical_margin"
xmlns:app="http://schemas.android.com/apk/res-auto">


<Spinner
    android:id="@+id/spinner"
    android:layout_width="150dp"
    android:layout_height="wrap_content"
    android:spinnerMode="dropdown"
    android:layout_below="@id/member_img"
    android:layout_marginTop="@dimen/activity_vertical_margin"
    android:background="@drawable/member_btn"
    android:padding="@dimen/activity_horizontal_margin"
    android:layout_marginStart="@dimen/activity_horizontal_margin"
    android:textColor="@color/colorAccent"
    app:position="@{0}"
    />
 </RelativeLayout>
 </layout>

App:position是你传递要选择的位置。

定制绑定

  @BindingAdapter(value={ "position"}, requireAll=false)
  public static void setSpinnerAdapter(Spinner spinner, int selected) 
  {

    final int [] selectedposition= new int[1];
    selectedposition[0]=selected;


    // custom adapter or you can set default adapter
        CustomSpinnerAdapter customSpinnerAdapter = new CustomSpinnerAdapter(spinner.getContext(), <arraylist you want to add to spinner>);
        spinner.setAdapter(customSpinnerAdapter);
            spinner.setSelection(selected,false);


    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

            String item = parent.getItemAtPosition(position).toString();
        if( position!=selectedposition[0]) {
                        selectedposition[0]=position;
            // do your stuff here
                    }
                }


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

        }
    });
}

你可以阅读更多关于自定义数据绑定在这里Android自定义Setter

NOTE

不要忘记在Gradle文件中启用数据绑定 android { .... 数据绑定{ Enabled = true } } 包括你的布局文件在<layout>标签