美文网首页
RecyclerView基本使用(加分割线)

RecyclerView基本使用(加分割线)

作者: FlyClound | 来源:发表于2018-07-06 15:00 被阅读0次

    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,源码

    github

    相关文章

      网友评论

          本文标题:RecyclerView基本使用(加分割线)

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