RecyclerView添加分割线

1,线性布局

列表图片
- 1,引入
compile ‘com.android.support:recyclerview-v7:27.1.1’
- 2,xml布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_linear_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</android.support.constraint.ConstraintLayout>
  • 3,Activity内容
public class RvLinearActivity extends AppCompatActivity {
    private android.support.v7.widget.RecyclerView rvlinearlist;
    private ArrayList<String> mData;
    private RvLinearAdapter mAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_linear);
        this.rvlinearlist = (RecyclerView) findViewById(R.id.rv_linear_list);

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        //设置方向,默认方向(垂直)
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        rvlinearlist.setLayoutManager(linearLayoutManager);

        mData = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            mData.add("频道"+i);
        }
        mAdapter = new RvLinearAdapter(this, mData);
        rvlinearlist.setAdapter(mAdapter);

        //添加下划线

    }
}
  • 4,adapter
public class RvLinearAdapter extends  RecyclerView.Adapter<RvLinearAdapter.ViewHolder>{

    private final LayoutInflater mLayoutInflater;
    private Context mContext;
    private List<String>mData;

    public RvLinearAdapter(Context context, List<String> data) {
        mContext = context;
        mData = data;
        mLayoutInflater = LayoutInflater.from(context);
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View inflate = mLayoutInflater.inflate(R.layout.item_rv_linear, parent, false);
        return new ViewHolder(inflate);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.tvText.setText(mData.get(position));
        //点击监听
        holder.tvText.setOnClickListener(v->{
            Toast.makeText(mContext, mData.get(position), Toast.LENGTH_SHORT).show();
        });
    }

    @Override
    public int getItemCount() {
        return mData.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder {
        TextView tvText;
        public ViewHolder(View itemView) {
            super(itemView);
            tvText=itemView.findViewById(R.id.tv_item_rv_linear_text);
        }
    }
}
  • 5,添加下划线
    1,添加默认分割线
    image.png
rvlinearlist.addItemDecoration(new DividerItemDecoration
                (this, LinearLayoutManager.VERTICAL));//默认类型的分割线

2,修改默认分割线
image.png

">    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:listDivider">@drawable/recyclerview_decoration</item>
</style>

recyclerview_decoration:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/red"/>
    <size android:height="1dp"/>
</shape>

3,头部也带分割线

//自定义
public class ListViewHeadDecoration extends RecyclerView.ItemDecoration {//从头部开始绘制

    private Drawable mDrawable;

    public ListViewHeadDecoration(Context context, int drawableId) {
        mDrawable = ContextCompat.getDrawable(context, drawableId);

    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            // 以下计算主要用来确定绘制的位置
            final int top = child.getTop() -mDrawable.getIntrinsicHeight()+
                    Math.round(ViewCompat.getTranslationY(child));
            final int bottom = top + mDrawable.getIntrinsicHeight();
            mDrawable.setBounds(left, top, right, bottom);
            mDrawable.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.set(0, mDrawable.getIntrinsicHeight(),0,0);
    }
}

//调用
    rvlinearlist.addItemDecoration(new ListViewHeadDecoration
                (this,R.drawable.listview_decoration));

头部不加分割线:

public class ListViewDecoration extends RecyclerView.ItemDecoration {

    private Drawable mDrawable;

    public ListViewDecoration(Context context, int drawableId) {
        mDrawable = ContextCompat.getDrawable(context, drawableId);
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount-1; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            // 以下计算主要用来确定绘制的位置
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDrawable.getIntrinsicHeight();
            mDrawable.setBounds(left, top, right, bottom);
            mDrawable.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.set(0, 0, 0, mDrawable.getIntrinsicHeight());
    }
}
2,网格布局添加分割线

image.png
- 1,Xml文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
    android:id="@+id/rv_linear_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="20dp"/>
</android.support.constraint.ConstraintLayout>
  • 2,Activity文件
public class GridLineActivity extends AppCompatActivity {
    private android.support.v7.widget.RecyclerView rvlinearlist;
    private ArrayList<String> mData;
    private GridAdapter mGridAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_linear);
        this.rvlinearlist = (RecyclerView) findViewById(R.id.rv_linear_list);

        initData();
        initAdapter();

    }

    private void initAdapter() {
        GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);
        rvlinearlist.setLayoutManager(gridLayoutManager);
//使用添加头和尾的适配器
        mGridAdapter = new GridAdapter(this, mData);
        rvlinearlist.setAdapter(mGridAdapter);
        //添加分割线
        //rvlinearlist.addItemDecoration(new Divider2(this));
        //添加分割线

        ItemDivider itemDivider = new ItemDivider();
        itemDivider.setDividerColor(Color.YELLOW).setDividerWith(5);
        rvlinearlist.addItemDecoration(itemDivider);
    }

    private void initData() {
        mData = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            mData.add("频道"+i);
        }
    }
}
  • 3,Adapter文件
public class GridAdapter extends  RecyclerView.Adapter<GridAdapter.ViewHolder>{

    private final LayoutInflater mLayoutInflater;
    private Context mContext;
    private List<String>mData;

    //Type
    private int TYPE_NORMAL = 1000;
    private int TYPE_HEADER = 1001;
    private int TYPE_FOOTER = 1002;


    public GridAdapter(Context context, List<String> data) {
        mContext = context;
        mData = data;
        mLayoutInflater = LayoutInflater.from(context);
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View inflate = mLayoutInflater.inflate(R.layout.item_rv_linear, parent, false);
        return new ViewHolder(inflate);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.tvText.setText(mData.get(position));
        //点击监听
        holder.tvText.setOnClickListener(v->{
            Toast.makeText(mContext, mData.get(position), Toast.LENGTH_SHORT).show();
        });
    }

    @Override
    public int getItemCount() {
        return mData.size();
    }

    @Override
    public int getItemViewType(int position) {
        return super.getItemViewType(position);
    }

    class ViewHolder extends RecyclerView.ViewHolder {
        TextView tvText;
        public ViewHolder(View itemView) {
            super(itemView);
            tvText=itemView.findViewById(R.id.tv_item_rv_linear_text);
        }
    }
}
  • 4,用到的添加分割线方法
    方法一:(这个也可以用到线性布局中)
public class ItemDivider extends RecyclerView.ItemDecoration {

      private int dividerWith = 1;
      private Paint paint;
      private RecyclerView.LayoutManager layoutManager;

      // 构造方法,可以在这里做一些初始化,比如指定画笔颜色什么的
      public ItemDivider() {  
          initPaint();
          paint.setColor(0xffff0000);     
      }   

      private void initPaint() {    
          if (paint == null) {        
             paint = new Paint(Paint.ANTI_ALIAS_FLAG);        
             paint.setStyle(Paint.Style.FILL);    
          }
      }

      public ItemDivider setDividerWith(int dividerWith) {    
         this.dividerWith = dividerWith;   
         return this;

      }

      public ItemDivider setDividerColor(int color) {    
          initPaint();    
          paint.setColor(color);    
          return this;
       } 

      /**     
       * 指定item之间的间距(就是指定分割线的宽度)   回调顺序 1     
       * @param outRect Rect to receive the output.      
       * @param view    The child view to decorate     
       * @param parent  RecyclerView this ItemDecoration is decorating     
       * @param state   The current state of RecyclerView.     
       */    
       @Override    
       public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
           super.getItemOffsets(outRect, view, parent, state);    
            if (layoutManager == null) {    
               layoutManager = parent.getLayoutManager();
            }
            // 适用 LinearLayoutManager 和 GridLayoutManager
            if (layoutManager instanceof LinearLayoutManager) {
               int orientation = ((LinearLayoutManager) layoutManager).getOrientation();    
               if (orientation == LinearLayoutManager.VERTICAL) {        
                   // 水平分割线将绘制在item底部        
                   outRect.bottom = dividerWith;    
               } else if (orientation == LinearLayoutManager.HORIZONTAL) {        
                   // 垂直分割线将绘制在item右侧        
                   outRect.right = dividerWith;   
               }    
               if (layoutManager instanceof GridLayoutManager) {
                   GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams) view.getLayoutParams();        
                   // 如果是 GridLayoutManager 则需要绘制另一个方向上的分割线       
                   if (orientation == LinearLayoutManager.VERTICAL && lp != null && lp.getSpanIndex() > 0) {            
                      // 如果列表是垂直方向,则最左边的一列略过            
                      outRect.left = dividerWith;        
                   } else if (orientation == LinearLayoutManager.HORIZONTAL && lp != null && lp.getSpanIndex() > 0) {            
                      // 如果列表是水平方向,则最上边的一列略过            
                      outRect.top = dividerWith;        
                   }    
               }
           }  
       }    

       /**     
        * 在item 绘制之前调用(就是绘制在 item 的底层)  回调顺序 2     
        * 一般分割线在这里绘制     
        * 看到canvas,对自定义控件有一定了解的话,就能想到为什么说给RecyclerView设置分割线更灵活了
        * @param c      Canvas to draw into     
        * @param parent RecyclerView this ItemDecoration is drawing into     
        * @param state  The current state of RecyclerView     
        */    
        @Override    
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            super.onDraw(c, parent, state);  
            // 这个值是为了补偿横竖方向上分割线交叉处间隙
            int offSet = (int) Math.ceil(dividerWith * 1f / 2);
            for (int i = 0; i < parent.getChildCount(); i++) {    
                View child = parent.getChildAt(i);    
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();   
                int left1 = child.getRight() + params.rightMargin;
                int right1 = left1 + dividerWith;
                int top1 = child.getTop() - offSet - params.topMargin;
                int bottom1 = child.getBottom() + offSet + params.bottomMargin;
                //绘制分割线(矩形)
                c.drawRect(left1, top1, right1, bottom1, paint);
                int left2 = child.getLeft() - offSet - params.leftMargin;
                int right2 = child.getRight() + offSet + params.rightMargin;
                int top2 = child.getBottom() + params.bottomMargin;
                int bottom2 = top2 + dividerWith;
                //绘制分割线(矩形)
                c.drawRect(left2, top2, right2, bottom2, paint);
             }         
        }    

        /**     
         * 在item 绘制之后调用(就是绘制在 item 的上层)  回调顺序 3     
         * 也可以在这里绘制分割线,和上面的方法 二选一     
         * @param c      Canvas to draw into     
         * @param parent RecyclerView this ItemDecoration is drawing into     
         * @param state  The current state of RecyclerView     
         */    
         @Override   
         public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {        
            super.onDrawOver(c, parent, state);    
         }
     }

直接调用:

  ItemDivider itemDivider = new ItemDivider();
        itemDivider.setDividerColor(Color.YELLOW).setDividerWith(5);
        rvlinearlist.addItemDecoration(itemDivider);

方法二:

public class Divider2 extends RecyclerView.ItemDecoration
{

    private static final int[] ATTRS = new int[] { android.R.attr.listDivider };
    private Drawable mDivider;

    public Divider2(Context context)
    {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state)
    {

        drawHorizontal(c, parent);
        drawVertical(c, parent);

    }

    private int getSpanCount(RecyclerView parent)
    {
        // 列数
        int spanCount = -1;
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager)
        {

            spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
        } else if (layoutManager instanceof StaggeredGridLayoutManager)
        {
            spanCount = ((StaggeredGridLayoutManager) layoutManager)
                    .getSpanCount();
        }
        return spanCount;
    }

    public void drawHorizontal(Canvas c, RecyclerView parent)
    {
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++)
        {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getLeft() - params.leftMargin;

//            final int right = child.getRight() + params.rightMargin
//                    + mDivider.getIntrinsicWidth();


            final int right = child.getRight() + params.rightMargin
                    + mDivider.getIntrinsicWidth();

            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawVertical(Canvas c, RecyclerView parent)
    {
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++)
        {
            final View child = parent.getChildAt(i);

            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();

            final int top = child.getTop() - params.topMargin;
            final int bottom = child.getBottom() + params.bottomMargin;
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicWidth();



            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
                                int childCount)
    {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager)
        {
            if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
            {
                return true;
            }
        } else if (layoutManager instanceof StaggeredGridLayoutManager)
        {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            if (orientation == StaggeredGridLayoutManager.VERTICAL)
            {
                if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
                {
                    return true;
                }
            } else
            {
                childCount = childCount - childCount % spanCount;
                if (pos >= childCount)// 如果是最后一列,则不需要绘制右边
                    return true;
            }
        }
        return false;
    }

    private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
                              int childCount)
    {


        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager)
        {
            childCount = childCount - childCount % spanCount;


//            if(childCount % spanCount == 0){
//            childCount=childCount-spanCount;
//        }else{
//            childCount = childCount - childCount % spanCount;
//        }


            if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
                return true;
        } else if (layoutManager instanceof StaggeredGridLayoutManager)
        {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            // StaggeredGridLayoutManager 且纵向滚动
            if (orientation == StaggeredGridLayoutManager.VERTICAL)
            {
                childCount = childCount - childCount % spanCount;
                // 如果是最后一行,则不需要绘制底部
                if (pos >= childCount)
                    return true;
            } else
            // StaggeredGridLayoutManager 且横向滚动
            {
                // 如果是最后一行,则不需要绘制底部
                if ((pos + 1) % spanCount == 0)
                {
                    return true;
                }
            }
        }

//        if(childCount % spanCount == 0){
//            childCount=childCount-spanCount;
//        }else{
//            childCount = childCount - childCount % spanCount;
//        }
//        if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
//            return true;

        return false;
    }


    private boolean isLastRaw2(RecyclerView parent, int pos, int spanCount,
                              int childCount)
    {

        if(childCount % spanCount == 0){
            childCount=childCount-spanCount;
        }else{
            childCount = childCount - childCount % spanCount;
        }
        if (pos >= childCount){
            // 如果是最后一行,则不需要绘制底部
            return true;
        }
        return false;
    }

//    @Override
//    public void getItemOffsets(Rect outRect, int itemPosition,
//                               RecyclerView parent)
//    {
//
        int left = column * mBuilder.dividerVerSize / spanCount;
        int right = mBuilder.dividerVerSize - (column + 1) * mBuilder.dividerVerSize / spanCount;
//
//
//
//
//
//        int spanCount = getSpanCount(parent);
//        int childCount = parent.getAdapter().getItemCount();
//
//        int column=itemPosition%spanCount;
//        int right= mDivider.getIntrinsicWidth()-(column+1)*mDivider.getIntrinsicWidth()/spanCount;
//        int left=column*mDivider.getIntrinsicWidth()/spanCount;
//
//        if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
//        {
//            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
//
//        } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
//        {
//
//            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
//        } else
//        {
//            outRect.set(left, 0, right,
//                    mDivider.getIntrinsicHeight());
//            //Log.i("MMM", "getItemOffsets: "+mDivider.getIntrinsicWidth()+"||"+ mDivider.getIntrinsicHeight());
//        }
//    }


    @Override
    public void getItemOffsets(Rect outRect, int itemPosition,
                               RecyclerView parent)
    {


        int spanCount = getSpanCount(parent);
        int childCount = parent.getAdapter().getItemCount();
        int left,top=0,right,bottom;
        int eachWidth = (spanCount - 1) * mDivider.getIntrinsicHeight() / spanCount;
        int dl = mDivider.getIntrinsicHeight() - eachWidth;
        left = itemPosition % spanCount * dl;
        right = eachWidth - left;
        bottom = mDivider.getIntrinsicHeight();
        if (isLastRaw(parent, itemPosition, spanCount, childCount)) {
            bottom = 0;
        }
        outRect.set(left, top, right, bottom);
//        if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
//        {
//            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
//        } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
//        {
//            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
//        } else
//        {
//            outRect.set(0, 0, mDivider.getIntrinsicWidth(),
//                    mDivider.getIntrinsicHeight());
//        }

    }


}

需要的style文件:

  <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

        <item name="android:listDivider">@drawable/listview_decoration</item>
    </style>

资源文件:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/red"/>
    <size android:height="10dp"
        android:width="10dp"/>
</shape>

使用:

rvlinearlist.addItemDecoration(new Divider2(this));
3,源码

源码下载

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值