在这个项目基础上扩展了一些属性,
扩展后项目
源码中比较有意思的部分是如何将上一次选中的数据在下一次展示下拉框时排除该条数据
-
初始化
ListPopupWindow
时, 设置ListPopupWindow
点击条目事件的回调方法,
在这里处理ListPopupWindow
中ListView
被点击的条目的索引值与该条目中数据在数据源List
中的索引值的运算关系./** * 初始化PopupWindow设置 * * @param context */ private void initPopup(Context context) { //创建ListPopupWindow popupWindow = new ListPopupWindow(context); //为PopupWindow设置背景色 popupWindow.setBackgroundDrawable(getResources().getDrawable(mPopupBgColor)); //设置动画为PopupWindow popupWindow.setAnimationStyle(mPopupAnim); //点击回调事件 popupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // The selected item is not displayed within the list, so when the selected position is equal to // the one of the currently selected item it gets shifted to the next item. // selectedIndex:该值代表Adapter数据源中,上一次被选中的数据对应的list索引值. // ListPopupWindow中被选中的条目索引值position,大于或者selectedIndex时, // 将position处理之后,转为被选中条目所对应的数据在数据源list中对应的索引值. // 这个地方有点绕,可以举例子来理解,比如数据源中数据为{A,B,C,D} // 展示时NiceSpinner控件出现"A",此时ListPopupWindow中三个条目分别为{B,C,D} // 当点击ListPopupWindow中第0个条目时,该条目中数据"B"对应的list数据源中索引其实为1,也就是selectedIndex=1. // 而当再次展示ListPopupWindow时, 因为selectedIndex=1,ListPopupWindow条目为0依旧展示数据源中0索引对应的数据"A",NiceSpinner控件展示数据"B" // 但条目1展示的数据,看NiceSpinnerAdapter中getItem()方法可知道,此时应该展示list数据源中索引为2对应的值"C". if (position >= selectedIndex && position < adapter.getCount()) { position++; } // selectedIndex 为当前选中数据在数据源中对应的list的索引值. selectedIndex = position; // 选中之后的回调方法, 将被选中数据的list索引传出去. if (onSpinnerItemSelectedListener != null) { onSpinnerItemSelectedListener.onItemSelected(NiceSpinner.this, view, position, id); } // 将当前选中数据在数据源中对应的list的索引值,设置到NiceSpinnerBaseAdapter中 adapter.setSelectedIndex(position); // 通过索引取得list中的数据,将数据展示到NiceSpinner上 setTextInternal(adapter.getItemInDataset(position)); // 选中数据之后让ListPopupWindow消失 dismissDropDown(); } }); // 是否触摸别的地方PopupWindow消失 popupWindow.setModal(true); // ListPopupWindow消失的回调 popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { @Override public void onDismiss() { // 如果箭头没有隐藏 if (!isArrowHidden) { // 此时箭头应该执行向下动画 animateArrow(false); } } }); }
-
上面分析的是点击
ListPopupWindow
中条目,下面还需要看看当展示ListPopupWindow
时,如何将上一次被选中的数据排除展示.
这里看的是ListPopupWindow
用的Adapter.上面和下面都会用到selectedIndex值, 这个需要好好理解.public abstract class NiceSpinnerBaseAdapter<T> extends BaseAdapter { @Override public int getCount() { //展示的条目个数永远都比源数据长度少一个,因为其中一个数据被展示到了NiceSpinner控件上. return items.size() - 1; } @Override public T getItem(int position) { // selectedIndex:该值代表Adapter数据源中,上一次被选中的数据对应的数据源list中索引值. // 假如,当ListPopupWindow展示第1条目时,上一次所选中selectedIndex =1, // 那么ListPopupWindow第1条目应该展示数据源list中索引为2的数据. if (position >= selectedIndex) { return items.get(position + 1); } else { return items.get(position); } } }
-
剩余其他代码是一些常规的操作.
-
效果图