美文网首页
Android-->RecyclerView分组悬浮标题(

Android-->RecyclerView分组悬浮标题(

作者: angcyo | 来源:发表于2017-04-27 08:50 被阅读313次

    客官先看图:
    https://github.com/angcyo/ContactsPicker/blob/master/screenshot/1%E6%9C%88-15-2017%2016-17-46.gif

    RecyclerView中实现分组功能, 和 实现分割线 使用的是相同原理. 就是手动绘制信息.

    都是继承RecyclerView.ItemDecoration

    分割线的实现传送门:http://blog.csdn.net/angcyo/article/details/52829707


    1:为分组信息腾出空间

    //这个方法就是用来描述是否需要给第二个参数view的上下左右腾出空间.
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        final RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();//布局管理器
        if (!(layoutManager instanceof LinearLayoutManager)) {
            throw new IllegalArgumentException("暂不支持 " + layoutManager.getClass().getSimpleName());
        }
    
        if (mGroupCallBack == null) {
            return;
        }
    
        final RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
        final int adapterPosition = layoutParams.getViewAdapterPosition();
        if (adapterPosition == 0) {
            //第一个位置, 肯定是有分组信息的
            //我这里需要支持横向和竖向,所以加了方向判断.可以取消掉.
            if (((LinearLayoutManager) layoutManager).getOrientation() == LinearLayoutManager.HORIZONTAL) {
                //为左边腾出空间
                outRect.set(mGroupCallBack.getGroupHeight(), 0, 0, 0);
            } else {
               //为上边腾出空间
                outRect.set(0, mGroupCallBack.getGroupHeight(), 0, 0);
            }
        } else {
            //上一个分组信息
            String preGroupText = mGroupCallBack.getGroupText(adapterPosition - 1);
            //当前的分组信息
            String groupText = mGroupCallBack.getGroupText(adapterPosition);
            if (!TextUtils.equals(preGroupText, groupText)) {
                //如果和上一个分组信息不相等
                if (((LinearLayoutManager) layoutManager).getOrientation() == LinearLayoutManager.HORIZONTAL) {
                    outRect.set(mGroupCallBack.getGroupHeight(), 0, 0, 0);
                } else {
                    outRect.set(0, mGroupCallBack.getGroupHeight(), 0, 0);
                }
            }
        }
    }
    

    2:空间已经给出来了,那么就是绘制你想要的信息了

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
      if (mGroupCallBack == null) {
          return;
      }
    
    //需要注意的就是, 绘制是从屏幕上布局了多少个子View开始的.
    //也就是说, 你并不需要考虑不在屏幕上View的情况.
    //通过parent.getChildCount()拿到的就是屏幕上布局了多少个子View的数量
      for (int i = 0; i < parent.getChildCount(); i++) {
          final View view = parent.getChildAt(i);
          final RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
          final int adapterPosition = layoutParams.getViewAdapterPosition();
          if (adapterPosition == 0) {
              //第一个位置, 肯定是有分组信息的
              mGroupCallBack.onGroupDraw(c, view, adapterPosition);
          } else {
              //上一个分组信息
              String preGroupText = mGroupCallBack.getGroupText(adapterPosition - 1);
              //当前的分组信息
              String groupText = mGroupCallBack.getGroupText(adapterPosition);
              if (!TextUtils.equals(preGroupText, groupText)) {
                  //如果和上一个分组信息不相等
                  mGroupCallBack.onGroupDraw(c, view, adapterPosition);
              }
          }
      }
    }
    

    通过以上2个方法, 已经可以实现分割线了.

    如果需要悬停效果, 那么就继续往下看.

    3:悬停效果
    onDrawOver方法和onDraw方法完全一样. 只不过名字不一样而已.
    你完全可以在onDraw方法中, 实现.
    但是官方竟然给了我们这种方法, 而且名字都取得那么好...我们又有什么理由不使用呢?

    @Override
     public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
         if (mGroupCallBack == null || parent.getChildCount() <= 0) {
             return;
         }
    
         boolean isHorizontal = ((LinearLayoutManager) parent.getLayoutManager()).getOrientation() == LinearLayoutManager.HORIZONTAL;
    
         final View view = parent.getChildAt(0);
         final RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
         final int adapterPosition = layoutParams.getViewAdapterPosition();
         if (adapterPosition == 0) {
             //第一个位置, 肯定是有分组信息的
             if ((isHorizontal ? view.getLeft() : view.getTop()) <= 0) {
                 mGroupCallBack.onGroupOverDraw(c, view, adapterPosition, 0);
             } else {
                 mGroupCallBack.onGroupOverDraw(c, view, adapterPosition, mGroupCallBack.getGroupHeight() - (isHorizontal ? view.getLeft() : view.getTop()));
             }
         } else {
             if (parent.getLayoutManager().getItemCount() > adapterPosition + 1) {
                 //下一个分组信息
                 String nextGroupText = mGroupCallBack.getGroupText(adapterPosition + 1);
                 //当前的分组信息
                 String groupText = mGroupCallBack.getGroupText(adapterPosition);
    
                 final View nextView = parent.getChildAt(1);
                 if (!TextUtils.equals(nextGroupText, groupText)) {
                     if ((isHorizontal ? nextView.getLeft() : nextView.getTop()) <= 0) {
                         mGroupCallBack.onGroupOverDraw(c, view, adapterPosition, 0);
                     } else {
                         mGroupCallBack.onGroupOverDraw(c, view, adapterPosition,
                                 Math.max(0, 2 * mGroupCallBack.getGroupHeight() - (isHorizontal ? nextView.getLeft() : nextView.getTop())));
                     }
                 } else {
                     mGroupCallBack.onGroupOverDraw(c, view, adapterPosition, 0);
                 }
             } else {
                 mGroupCallBack.onGroupOverDraw(c, view, adapterPosition, 0);
             }
         }
     }
    

    开源地址:https://github.com/angcyo/ContactsPicker


    至此: 文章就结束了,如有疑问: QQ群 Android:274306954 Swift:399799363 欢迎您的加入.

    相关文章

      网友评论

          本文标题:Android-->RecyclerView分组悬浮标题(

          本文链接:https://www.haomeiwen.com/subject/ixlgzttx.html