最近使用Spinner时,发现点击同一条目便不再回调OnItemSelectedListener,很多文章解释的很好,但是给出的解决办法有些是有Bug的,我这里整理两种亲测有效的解决办法,直接加到代码里面就能用。
方法一
给Spinner多加一个回调,每次选择后,重置里面的mOldSelectedPosition属性值
spinner.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
@Override
public void onChildViewAdded(View parent, View child) {
log.info("onChildViewAdded--------------");
}
@Override
public void onChildViewRemoved(View parent, View child) {
log.info("onChildViewRemoved--------------");
try {
Class<?> clazz = AdapterView.class;
Field mOldSelectedPosition = clazz.getDeclaredField("mOldSelectedPosition");
mOldSelectedPosition.setAccessible(true);
mOldSelectedPosition.setInt(services_spinner,AdapterView.INVALID_POSITION);
} catch (Exception e) {
e.printStackTrace();
}
}
});
方法二
自定义一个类,继承Spinner,当选中同一条目时,手动触发OnItemSelectedListener的onItemSelected()方法,使用时直接在XML布局里面使用这个类就可以
package com.demo.xxx;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Spinner;
@SuppressLint("AppCompatCustomView")
public class ReSpinner extends Spinner {
public boolean isDropDownMenuShown = false;//标志下拉列表是否正在显示
public ReSpinner(Context context) {
super(context);
}
public ReSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ReSpinner(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setSelection(int position, boolean animate) {
boolean sameSelected = position == getSelectedItemPosition();
super.setSelection(position, animate);
if (sameSelected && getOnItemSelectedListener() != null) {
// 如果选择项是Spinner当前已选择的项,则 OnItemSelectedListener并不会触发,因此这里手动触发回调
getOnItemSelectedListener().onItemSelected(this, getSelectedView(), position, getSelectedItemId());
}
}
@Override
public boolean performClick() {
this.isDropDownMenuShown = true;
return super.performClick();
}
public boolean isDropDownMenuShown() {
return isDropDownMenuShown;
}
public void setDropDownMenuShown(boolean isDropDownMenuShown) {
this.isDropDownMenuShown = isDropDownMenuShown;
}
@Override
public void setSelection(int position) {
boolean sameSelected = position == getSelectedItemPosition();
super.setSelection(position);
if (sameSelected && getOnItemSelectedListener() != null) {
getOnItemSelectedListener().onItemSelected(this, getSelectedView(), position, getSelectedItemId());
}
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
}
推荐使用第二种解决办法,适合项目中有多个Spinner的情况,第一种解决办法适合处理其中某一个Spinner有这个需求的情况