如何让onItemSelected从一个新实例化的Spinner上触发?

我想到了一些不太好的方法来解决这个问题,但是我知道我必须错过一些东西。

我的onItemSelected立即启动,没有任何与用户的交互,这是不受欢迎的行为。 我希望用户界面等待,直到用户select一些东西,然后再做任何事情。

我甚至尝试在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. } } } 

我会期望您的解决scheme工作 – 我虽然select事件不会触发,如果您设置适配器设置侦听器之前。

也就是说,一个简单的布尔标志将允许你检测stream氓第一select事件,并忽略它。

Runnables的使用完全不正确。

使用setSelection(position, false);setOnItemSelectedListener(listener)之前的初始select中,

通过这种方式,您可以设置您的select,而不会导致选中的侦听器被调用的animation。 但是监听器是空的,所以没有任何运行。 然后你的听众被分配。

所以按照这个确切的顺序:

 Spinner s = (Spinner)Util.findViewById(view, R.id.sound, R.id.spinner); s.setAdapter(adapter); s.setSelection(position, false); s.setOnItemSelectedListener(listener); 

参考Dan Dyer的答案,尝试在post(Runnable)方法中注册OnSelectListener

 spinner.post(new Runnable() { public void run() { spinner.setOnItemSelectedListener(listener); } }); 

通过这样做,最终发生了希望的行为。

在这种情况下,这也意味着听众只会触发更改的项目。

我创build了一个小的实用程序方法来更改Spinnerselect,而不通知用户:

 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); } }); } }); } 

它将禁用侦听器,更改select,然后重新启用侦听器。

诀窍是调用与UI线程是asynchronous的,所以你必须在连续的处理程序文章中进行。

不幸的是,似乎这个问题的两个最常见的解决scheme,即统计callback事件和发布Runnable来设置callback在以后的时间都可以失败,例如,启用辅助function选项时。 这是一个帮助类,解决这些问题。 进一步的补充是在注释块中。

 import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.Spinner; import android.widget.SpinnerAdapter; /** * Spinner Helper class that works around some common issues * with the stock Android Spinner * * A Spinner will normally call it's OnItemSelectedListener * when you use setSelection(...) in your initialization code. * This is usually unwanted behavior, and a common work-around * is to use spinner.post(...) with a Runnable to assign the * OnItemSelectedListener after layout. * * If you do not call setSelection(...) manually, the callback * may be called with the first item in the adapter you have * set. The common work-around for that is to count callbacks. * * While these workarounds usually *seem* to work, the callback * may still be called repeatedly for other reasons while the * selection hasn't actually changed. This will happen for * example, if the user has accessibility options enabled - * which is more common than you might think as several apps * use this for different purposes, like detecting which * notifications are active. * * Ideally, your OnItemSelectedListener callback should be * coded defensively so that no problem would occur even * if the callback was called repeatedly with the same values * without any user interaction, so no workarounds are needed. * * This class does that for you. It keeps track of the values * you have set with the setSelection(...) methods, and * proxies the OnItemSelectedListener callback so your callback * only gets called if the selected item's position differs * from the one you have set by code, or the first item if you * did not set it. * * This also means that if the user actually clicks the item * that was previously selected by code (or the first item * if you didn't set a selection by code), the callback will * not fire. * * To implement, replace current occurrences of: * * Spinner spinner = * (Spinner)findViewById(R.id.xxx); * * with: * * SpinnerHelper spinner = * new SpinnerHelper(findViewById(R.id.xxx)) * * SpinnerHelper proxies the (my) most used calls to Spinner * but not all of them. Should a method not be available, use: * * spinner.getSpinner().someMethod(...) * * Or just add the proxy method yourself :) * * (Quickly) Tested on devices from 2.3.6 through 4.2.2 * * @author Jorrit "Chainfire" Jongma * @license WTFPL (do whatever you want with this, nobody cares) */ public class SpinnerHelper implements OnItemSelectedListener { private final Spinner spinner; private int lastPosition = -1; private OnItemSelectedListener proxiedItemSelectedListener = null; public SpinnerHelper(Object spinner) { this.spinner = (spinner != null) ? (Spinner)spinner : null; } public Spinner getSpinner() { return spinner; } public void setSelection(int position) { lastPosition = Math.max(-1, position); spinner.setSelection(position); } public void setSelection(int position, boolean animate) { lastPosition = Math.max(-1, position); spinner.setSelection(position, animate); } public void setOnItemSelectedListener(OnItemSelectedListener listener) { proxiedItemSelectedListener = listener; spinner.setOnItemSelectedListener(listener == null ? null : this); } public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (position != lastPosition) { lastPosition = position; if (proxiedItemSelectedListener != null) { proxiedItemSelectedListener.onItemSelected( parent, view, position, id ); } } } public void onNothingSelected(AdapterView<?> parent) { if (-1 != lastPosition) { lastPosition = -1; if (proxiedItemSelectedListener != null) { proxiedItemSelectedListener.onNothingSelected( parent ); } } } public void setAdapter(SpinnerAdapter adapter) { if (adapter.getCount() > 0) { lastPosition = 0; } spinner.setAdapter(adapter); } public SpinnerAdapter getAdapter() { return spinner.getAdapter(); } public int getCount() { return spinner.getCount(); } public Object getItemAtPosition(int position) { return spinner.getItemAtPosition(position); } public long getItemIdAtPosition(int position) { return spinner.getItemIdAtPosition(position); } public Object getSelectedItem() { return spinner.getSelectedItem(); } public long getSelectedItemId() { return spinner.getSelectedItemId(); } public int getSelectedItemPosition() { return spinner.getSelectedItemPosition(); } public void setEnabled(boolean enabled) { spinner.setEnabled(enabled); } public boolean isEnabled() { return spinner.isEnabled(); } } 

我处于类似的情况,我有一个简单的解决scheme为我工作。

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

当你使用第二个方法setSelected(int position, boolean animate)和假animation标志,你得到的select没有触发onItemSelected侦听器。

当我不想要的时候,我已经有很多问题了,所有的答案都是不可靠的。 他们工作 – 但只是有时候。 你最终会遇到他们会失败的情况,并将错误引入你的代码。

对我而言,最后select的索引存储在一个variables中,并在侦听器中进行评估。 如果它与新select的索引相同,则不做任何事情并返回,否则继续与侦听器。 做这个:

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

相信我,当我这样说时,这是迄今为止最可靠的解决scheme。 黑客,但它的作品!

为了充实一下使用onTouchListener来区分自动调用setOnItemSelectedListener(这是Activity初始化等的一部分)与由实际用户交互触发的调用之间的区别,我在尝试了一些其他build议发现它使用最less的代码行很好。

只需为您的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; 
 spinner.setSelection(Adapter.NO_SELECTION, false); 

在长时间拉出头发之后,我创build了自己的Spinner类。 我已经添加了一个方法,它适当地断开和连接侦听器。

 public class SaneSpinner extends Spinner { public SaneSpinner(Context context) { super(context); } public SaneSpinner(Context context, AttributeSet attrs) { super(context, attrs); } public SaneSpinner(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } // set the ceaseFireOnItemClickEvent argument to true to avoid firing an event public void setSelection(int position, boolean animate, boolean ceaseFireOnItemClickEvent) { OnItemSelectedListener l = getOnItemSelectedListener(); if (ceaseFireOnItemClickEvent) { setOnItemSelectedListener(null); } super.setSelection(position, animate); if (ceaseFireOnItemClickEvent) { setOnItemSelectedListener(l); } } } 

像这样在你的XML中使用它:

 <my.package.name.SaneSpinner android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/mySaneSpinner" android:entries="@array/supportedCurrenciesFullName" android:layout_weight="2" /> 

你所要做的就是在通货膨胀和呼叫集select之后检索SaneSpinner的实例:

 mMySaneSpinner.setSelection(1, true, true); 

借此,不会触发任何事件,并且用户交互不会中断。 这减less了我的代码复杂度很多。 这应该包含在Android的股票,因为它确实是一个PITA。

如果您推迟添加侦听器直到布局完成,那么布局阶段没有不需要的事件:

 spinner.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // Ensure you call it only once works for JELLY_BEAN and later spinner.getViewTreeObserver().removeOnGlobalLayoutListener(this); // add the listener spinner.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { // check if pos has changed // then do your work } @Override public void onNothingSelected(AdapterView<?> arg0) { } }); } }); 

我有一个非常简单的答案,100%肯定它的工作原理:

 boolean Touched=false; // this aa global variable public void changetouchvalue() { Touched=true; } // this code is written just before onItemSelectedListener spinner.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { System.out.println("Real touch felt."); changetouchvalue(); return false; } }); //inside your spinner.SetonItemSelectedListener , you have a function named OnItemSelected iside that function write the following code if(Touched) { // the code u want to do in touch event } 

我发现了更多优雅的解决scheme。 它涉及计算ArrayAdapter(在你的情况“适配器”)被调用的次数。 假设你有一个微调,你打电话给:

 int iCountAdapterCalls = 0; 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); 

在onCreate之后声明一个int计数器,然后在onItemSelected()方法中放入一个“if”条件来检查初始化程序被调用的次数。 在你的情况下,你只需要调用它一次:

 if(iCountAdapterCalls < 1) { iCountAdapterCalls++; //This section executes in onCreate, during the initialization } else { //This section corresponds to user clicks, after the initialization } 

如果您在代码中进行select,则会发生这种情况;

  mSpinner.setSelection(0); 

而不是上面的语句使用

  mSpinner.setSelection(0,false);//just simply do not animate it. 

编辑:此方法不适用于Mi Android版Mi UI。

我的小小贡献是上面几个适合我几次的变体。

声明一个整数variables作为默认值(或上次使用的值保存在首选项中)。 使用spinner.setSelection(myDefault)在侦听器注册之前设置该值。 在onItemSelected检查新的微调值是否等于您在运行任何进一步的代码之前分配的值。

如果用户再次select相同的值,则具有不运行代码的附加优点。

遇到同样的问题后,我使用标签来解决这个问题。 背后的想法很简单:只要以编程方式更改微调框,请确保标签反映所选位置。 在监听器中,然后检查所选位置是否等于标签。 如果是这样,那么微调器的select就会被编程改变。

以下是我的新“spinner代理”类:

 package com.samplepackage; import com.samplepackage.R; import android.widget.Spinner; public class SpinnerFixed { private Spinner mSpinner; public SpinnerFixed(View spinner) { mSpinner = (Spinner)spinner; mSpinner.setTag(R.id.spinner_pos, -2); } public boolean isUiTriggered() { int tag = ((Integer)mSpinner.getTag(R.id.spinner_pos)).intValue(); int pos = mSpinner.getSelectedItemPosition(); mSpinner.setTag(R.id.spinner_pos, pos); return (tag != -2 && tag != pos); } public void setSelection(int position) { mSpinner.setTag(R.id.spinner_pos, position); mSpinner.setSelection(position); } public void setSelection(int position, boolean animate) { mSpinner.setTag(R.id.spinner_pos, position); mSpinner.setSelection(position, animate); } // If you need to proxy more methods, use "Generate Delegate Methods" // from the context menu in Eclipse. } 

您还需要一个XML文件,并在您的Values目录中设置标签。 我将文件命名为spinner_tag.xml ,但这取决于您。 它看起来像这样:

 <resources xmlns:android="http://schemas.android.com/apk/res/android"> <item name="spinner_pos" type="id" /> </resources> 

现在更换

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

在你的代码中

 SpinnerFixed myspinner; ... myspinner = new SpinnerFixed(findViewById(R.id.myspinner)); 

让你的处理程序看起来像这样:

 myspinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (myspinner.isUiTriggered()) { // Code you want to execute only on UI selects of the spinner } } @Override public void onNothingSelected(AdapterView<?> parent) { } }); 

函数isUiTriggered()将返回true,当且仅当用户更改了微调器。 请注意,这个函数有一个副作用 – 它将设置标签,所以在同一个监听器调用中的第二个调用总是返回false

这个包装器也将处理在创build布局的过程中被调用的监听器的问题。

玩得开心,延斯。

由于没有为我工作,我有超过1微调在我看来(恕我直言持有布尔图是一个矫枉过正)我使用标签来计算点击:

 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) { } }); 

我会尽力打电话

 spinner.setOnItemSelectedListener(new MyOnItemSelectedListener()); 

在你调用setAdapter()之后。 也可以尝试在适配器之前调用。

你总是有解决scheme去与子类化,在那里你可以包装一个布尔标志到你的覆盖setAdapter方法跳过事件。

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

我subclassed android.widget.Spinner和微小的增加。 相关部分如下。 这个解决scheme为我工作。

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

这也不是一个优雅的解决scheme。 实际上它就是Rube-Goldberg,但它似乎起作用。 我通过扩展数组适配器并覆盖它的getDropDownView来确保微调器至less被使用了一次。 在新的getDropDownView方法中,我设置了一个布尔标志来显示下拉菜单至less被使用了一次。 在设置标志之前,我忽略了对监听者的调用。

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

如果你需要在飞行中重新创build活动,例如:改变主题,一个简单的标志/计数器将无法正常工作

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

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

我用最简单的方法了:

 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) { } }); 

完成

 if () { spinner.setSelection(0);// No reaction to create spinner !!! } else { spinner.setSelection(intPosition); } spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (position > 0) { // real selection } } @Override public void onNothingSelected(AdapterView<?> parent) { } }); 

devise一个常用的微调器,只需input数据并获取用户select的优点:

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); 

获取用户select:

 @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())); } } } } 

这是我的最终和易于使用的解决scheme:

 public class ManualSelectedSpinner extends Spinner { //get a reference for the internal listener private OnItemSelectedListener mListener; public ManualSelectedSpinner(Context context) { super(context); } public ManualSelectedSpinner(Context context, AttributeSet attrs) { super(context, attrs); } public ManualSelectedSpinner(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public void setOnItemSelectedListener(@Nullable OnItemSelectedListener listener) { mListener = listener; super.setOnItemSelectedListener(listener); } public void setSelectionWithoutInformListener(int position){ super.setOnItemSelectedListener(null); super.setSelection(position); super.setOnItemSelectedListener(mListener); } public void setSelectionWithoutInformListener(int position, boolean animate){ super.setOnItemSelectedListener(null); super.setSelection(position, animate); super.setOnItemSelectedListener(mListener); } } 

Use the default setSelection(...) for default behaviour or use setSelectionWithoutInformListener(...) for selecting an item in the spinner without triggering OnItemSelectedListener callback.

I need to use mSpinner in ViewHolder, so the flag mOldPosition is set in the anonymous inner class.

 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 } }); 

I would store the initial index during creation of the onClickListener object.

  int thisInitialIndex = 0;//change as needed myspinner.setSelection(thisInitialIndex); myspinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { int initIndex = thisInitialIndex; @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (id != initIndex) { //if selectedIndex is the same as initial value // your real onselecteditemchange event } } @Override public void onNothingSelected(AdapterView<?> parent) { } }); 

My solution uses onTouchListener but doesn't restricts from its use. It creates a wrapper for onTouchListener if necessary where setup onItemSelectedListener .

 public class Spinner extends android.widget.Spinner { /* ...constructors... */ private OnTouchListener onTouchListener; private OnItemSelectedListener onItemSelectedListener; @Override public void setOnItemSelectedListener(OnItemSelectedListener listener) { onItemSelectedListener = listener; super.setOnTouchListener(wrapTouchListener(onTouchListener, onItemSelectedListener)); } @Override public void setOnTouchListener(OnTouchListener listener) { onTouchListener = listener; super.setOnTouchListener(wrapTouchListener(onTouchListener, onItemSelectedListener)); } private OnTouchListener wrapTouchListener(final OnTouchListener onTouchListener, final OnItemSelectedListener onItemSelectedListener) { return onItemSelectedListener != null ? new OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { Spinner.super.setOnItemSelectedListener(onItemSelectedListener); return onTouchListener != null && onTouchListener.onTouch(view, motionEvent); } } : onTouchListener; } } 

I might be answering too late over the post, however I managed to achieve this using Android Data binding library Android Databinding . I created a custom binding to make sure listener is not called until selected item is changed so even if user is selecting same position over and over again event is not fired.

Layout xml file

  <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 is where you are passing position to be selected.

Custom binding

  @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) { } }); } 

You can read more about custom data binding here Android Custom Setter

注意

  1. Don't forget to enable databinding in your Gradle file

      android { .... dataBinding { enabled = true } } 
  2. Include your layout files in <layout> tags

 mYear.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View arg1, int item, long arg3) { if (mYearSpinnerAdapter.isEnabled(item)) { } } @Override public void onNothingSelected(AdapterView<?> parent) { } });