使用反射让Spinner选择同一选项时触发onItemSelected事件
翻看源码,Spinner判断是否触发onItemSelected,是在它的基类AdapterView里面做的:
void checkSelectionChanged() { if ((mSelectedPosition != mOldSelectedPosition) || (mSelectedRowId != mOldSelectedRowId)) { selectionChanged(); mOldSelectedPosition = mSelectedPosition; mOldSelectedRowId = mSelectedRowId; } }
方法checkSelectionChanged和变量mOldSelectedPosition都是AdapterView私有的,我们无法继承Spinner重写之。不过,利用java的反射,我们可以暴力修改mOldSelectedPosition的值:
new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // TODO Auto-generated method stub try { //以下三行代码是解决问题所在 Field field = AdapterView.class.getDeclaredField("mOldSelectedPosition"); field.setAccessible(true); //设置mOldSelectedPosition可访问 field.setInt(spinner, AdapterView.INVALID_POSITION); //设置mOldSelectedPosition的值 } catch (Exception e) { e.printStackTrace(); } } @Override public void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub } };
我们每次选择之后,就更改mOldSelectedPosition的值,使得每次mSelectedPosition != mOldSelectedPosition判断总是为true,那么总会触发onItemSelected,达到我们的目的了。
通过代码实现Spinner的选中事件:
spinner.performItemClick(subOrdersListView.getChildAt(orderMenuPosition), orderMenuPosition,
subOrdersListView.getItemIdAtPosition(orderMenuPosition));