Andoird Nice Spinner源码解析

18 篇文章 1 订阅
15 篇文章 0 订阅

在这个项目基础上扩展了一些属性,
扩展后项目
源码中比较有意思的部分是如何将上一次选中的数据在下一次展示下拉框时排除该条数据

  • 初始化ListPopupWindow 时, 设置ListPopupWindow点击条目事件的回调方法,
    在这里处理ListPopupWindowListView被点击的条目的索引值与该条目中数据在数据源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);
          }
      }
    }
    
  • 剩余其他代码是一些常规的操作.

  • 效果图

    效果图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值