Spinner的setOnItemSelectedListener选中同一选项不触发Toast问题求助
解决Spinner重复选中同一选项不触发回调的问题
我明白你的问题了——Android原生的Spinner默认只会在选中的位置发生变化时才会调用onItemSelected方法,所以当你重复点击同一个选项时,这个回调不会被触发,自然也就不会弹出你想要的Toast提示。下面给你两种可行的解决方案:
方法一:自定义Spinner实现重复选中触发回调
这种方法最彻底,通过自定义Spinner控件,让它在用户重复选中同一选项时也能触发onItemSelected回调。
首先创建一个自定义Spinner类:
public class ReSelectSpinner extends androidx.appcompat.widget.AppCompatSpinner { private OnItemSelectedListener mInternalListener; private int mLastSelectedPosition = -1; public ReSelectSpinner(Context context) { super(context); init(); } public ReSelectSpinner(Context context, AttributeSet attrs) { super(context, attrs); init(); } public ReSelectSpinner(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { super.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { // 如果是重复选中同一位置,也触发外部监听 if (mInternalListener != null) { mInternalListener.onItemSelected(parent, view, position, id); } mLastSelectedPosition = position; } @Override public void onNothingSelected(AdapterView<?> parent) { if (mInternalListener != null) { mInternalListener.onNothingSelected(parent); } } }); } @Override public boolean performClick() { // 记录当前选中的位置,为后续判断做准备 mLastSelectedPosition = getSelectedItemPosition(); return super.performClick(); } @Override public void setOnItemSelectedListener(OnItemSelectedListener listener) { mInternalListener = listener; } }
然后在你的布局文件里,把原来的Spinner替换成这个自定义的ReSelectSpinner:
<com.yourpackage.ReSelectSpinner android:id="@+id/sp" android:layout_width="match_parent" android:layout_height="wrap_content" />
最后保留你原来的监听代码即可,现在重复选中同一选项时,onItemSelected会被正常触发,你的Toast也会弹出来了。
方法二:通过监听下拉列表Item点击实现(无需自定义控件)
如果你不想自定义控件,可以通过反射获取Spinner的下拉列表,给它设置Item点击监听,这样不管用户点击哪个选项(包括重复点击同一选项),都会触发你的逻辑。
首先把原来的回调逻辑提取成一个单独的方法,方便复用:
private void handleSpinnerSelection(int position) { if(position == 1){ if(turismo1.size() != 0){ // 你的原有代码 }else{ Toast.makeText(getApplicationContext(), "No hay turismos", Toast.LENGTH_LONG).show(); l.setAdapter(adaptador1); } }else if(position == 2){ // 你的原有代码 }else{ Toast.makeText(getApplicationContext(), "No hay transportes",Toast.LENGTH_LONG).show(); l.setAdapter(adaptador2); } }
然后在设置Spinner Adapter之后,添加以下代码:
// 获取Spinner的下拉列表弹窗 try { Field popupField = androidx.appcompat.widget.AppCompatSpinner.class.getDeclaredField("mPopup"); popupField.setAccessible(true); ListPopupWindow listPopup = (ListPopupWindow) popupField.get(sp); // 给下拉列表的ListView设置Item点击监听 listPopup.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 手动设置Spinner选中该位置 sp.setSelection(position); // 执行你的逻辑 handleSpinnerSelection(position); } }); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); }
最后,你原来的setOnItemSelectedListener可以保留(处理Spinner初始化时的选中事件),也可以去掉,因为现在下拉列表的点击已经会触发你的逻辑了。
这两种方法都能解决你的问题,你可以根据自己的需求选择其中一种。
内容的提问来源于stack exchange,提问作者David Arguedas
相关产品推荐
相关产品推荐

