RecyclerView系列之(2):为RecyclerView添加分隔线

android中RecyclerView的简单使用(二)——分割线 如果你觉得这些内容对你有帮助,可以扫码领取!!!! 阅读详情

一. 理解ListView和RecyclerView中的ChildView

在讲为Item加入分割线本质的前,先来介绍,认识一下ChildView,也就是平时我们用到的ListView,RecyclerView中的getChildAt(int position)这个返回的ChildView是哪一部分?到底是哪一部分呢?一开始的时候,我理解错了,但是经过下面两张图这么一比较,你就明白了:



Item布局layout_margin == 0


Item布局Layout_margin == 16dp

下面看代码的区别:
第一张图的代码, 也就是每一个list_item的布局文件(下同)如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"             
 android:orientation="vertical"             
 android:layout_width="match_parent"              
 android:layout_height="50dp">    
      <TextView        
        android:id="@+id/list_item"        
        android:layout_width="match_parent" 
        android:layout_height="match_parent"        
        android:gravity="center"        
        android:textSize="20sp"        
        android:textColor="#262526"        
        android:background="#08da1d"/>
</LinearLayout>

第二张图的代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"              
 android:orientation="vertical"             
 android:layout_width="match_parent"              
 android:layout_height="50dp"
 android:layout_margin="16dp">    
      <TextView        
        android:id="@+id/list_item"        
        android:layout_width="match_parent" 
        android:layout_height="match_parent"        
        android:gravity="center"        
        android:textSize="20sp"        
        android:textColor="#262526"        
        android:background="#08da1d"/>
</LinearLayout>

仔细看一下,它们的不同之处, 就是第二个图的代码中多了:

android:layout_margin = "16dp"

就多这一句而已。

所以到这里我们应该知道了ChildView是哪一部分了,就是图二中绿色这一部分,边距这一部分并不属于ChildView, 而是属于ChildView的布局。

这样我们了解ChildView之后,下面再来理解加入分隔线的原理就简单多了。

二. 理解加入分隔线的原理

在ListView中,Google为我们提供了SetDivider(Drawable divider)这样的方法来设置分隔线,那么在RecyclerView中,Google又为我们提供了什么样的方法去添加分隔线呢?通过查看官方文档,它,提供了:addItemDecoration(RecyclerView.ItemDecoration decor)这个方法了设置分隔线,那问题又来了,RecyclerView.ItemDecoration是什么东西呢?继续查:然后发现如下:它原来是一个类,里面封装了三个方法:
(1)void getItemOffsets ()
(2)void onDraw ()
(3)void onDrawOver ()


通过上面的三个方法,可以看出,这是要自己直接画上去,准确的说这几个方法是:添加Divider,主要是找到添加Divider的位置, 而Divider是在drawable文件中写好了的。 利用onDraw和onDrawOver都差不多,我们在创建自己的Decoration类继承RecyclerView.ItemDecoration的时候,我们只要重写getItemOffsets(),还有onDraw()和onDrawOver两者其中之一就可以了.


那getItemOffsets()方法有什么用呢?从字面意思就是Item要偏移, 由于我们在Item和Item之间加入了分隔线,线其实本质就是一个长方形,也是用户自定义的,既然线也有长宽高,就画横线来说,上面的Item加入了分隔线,那下面的Item就要往下平移,平移的量就是分隔线的高度。不理解每关系,后面看代码就容易理解了。


现在我们知道了如何添加了,就是通过画,那到底是画在哪里呢?画的位置又怎么确定呢?下面看图:



分隔线的位置图

我现在拿画横线来说,从上面这个图中,我们很容易就可以看到,我们画分隔线的位置,是在每一个Item的布局之间,注意:是布局之间。

好了,我们确定了画在哪里,那我们怎么确定画线的具体的坐标位置呢?也就是我们要确定:分隔线的left, top, right, Bottom. 在Adapter中,我们很容易通过parent(这个parent它其实就是我们能看到的部分)获取每一个childView:
(1)left:parent.getPaddingLeft()
(2)right: parent. getWidth()-parent.getPaddingRight();
(3)top : 就是红线的上面:我们通过ChildView.getBottom()来得到这个Item的底部的高度,也就是蓝线位置,蓝线和红线之间间距:就是这个Item布局文件的:layout_marginBottom, 然后top的位置就是两者之和。
(4)bttom: 就是top加上分隔线的高度:top+线高


通过上面的解析,你也许知道了加入分隔线的原理,不理解也没有关系,说也不是说得很清楚,下面直接上代码,通过代码来理解。

三. Talk is cheap, show you the code.

(1)首先,先来看主布局文件:activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.study.wnw.recyclerviewdivider.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
       android:layout_height="match_parent">    
    </android.support.v7.widget.RecyclerView>
</android.support.design.widget.CoordinatorLayout>

我在这里面仅仅加入了一个RecyclerView


(2)RecyclerView里面每个Item的布局文件:item_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent" 
              android:layout_height="50dp"
              android:layout_margin="16sp">
    <TextView
        android:id="@+id/list_item"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textSize="20sp"
        android:textColor="#f7f4f7"
        android:background="#08da1d"/>
</LinearLayout>

这也没有什么可讲的,就是在里面添加一个TextView用来显示文本


(3)我们RecyclerView的适配器MyAdapater.java:
package com.study.wnw.recyclerviewdivider;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/** * Created by wnw on 16-5-22. */
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    //定义一个集合,接收从Activity中传递过来的数据和上下文
    private List<String> mList;
    private Context mContext;

    MyAdapter(Context context, List<String> list){
        this.mContext = context;
        this.mList = list;
    }

    //得到child的数量
    @Override
    public int getItemCount() {
        return mList.size();
    }

    //创建ChildView
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View layout = LayoutInflater.from(mContext).inflate(R.layout.item_view, parent, false);
        return new MyHolder(layout);
    }

    //将数据绑定到每一个childView中
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof MyHolder){
            final String itemText = mList.get(position);
            ((MyHolder)holder).tv.setText(itemText);
        }
    }

    // 通过holder的方式来初始化每一个ChildView的内容
    class MyHolder extends RecyclerView.ViewHolder{
        TextView tv;
        public MyHolder(View itemView) {
            super(itemView);
            tv = (TextView)itemView.findViewById(R.id.list_item);
        }
    }
}

好了,这里也没有什么好讲的,也不是我们这篇文章的重点,下面重点来了。


(4)我们自定义的MyDecoration.java:(继承RecyclerView.ItemDecoration)
package com.study.wnw.recyclerviewdivider;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;

/** * Created by wnw on 16-5-22. */

public class MyDecoration extends RecyclerView.ItemDecoration{

    private Context mContext;
    private Drawable mDivider;
    private int mOrientation;
    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

    //我们通过获取系统属性中的listDivider来添加,在系统中的AppTheme中设置
    public static final int[] ATRRS  = new int[]{
            android.R.attr.listDivider
    };

    public MyDecoration(Context context, int orientation) {
        this.mContext = context;
        final TypedArray ta = context.obtainStyledAttributes(ATRRS);
        this.mDivider = ta.getDrawable(0);
        ta.recycle();
        setOrientation(orientation);
    }

    //设置屏幕的方向
    public void setOrientation(int orientation){
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST){
            throw new IllegalArgumentException("invalid orientation");        }        mOrientation = orientation;
    } 

   @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (mOrientation == HORIZONTAL_LIST){
            drawVerticalLine(c, parent, state);
        }else {
            drawHorizontalLine(c, parent, state);
        }
    }

    //画横线, 这里的parent其实是显示在屏幕显示的这部分
    public void drawHorizontalLine(Canvas c, RecyclerView parent, RecyclerView.State state){
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++){
            final View child = parent.getChildAt(i);

            //获得child的布局信息
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)child.getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
            //Log.d("wnw", left + " " + top + " "+right+"   "+bottom+" "+i);
        }
    }

    //画竖线
    public void drawVerticalLine(Canvas c, RecyclerView parent, RecyclerView.State state){
        int top = parent.getPaddingTop();
        int bottom = parent.getHeight() - parent.getPaddingBottom();
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++){
            final View child = parent.getChildAt(i); 

           //获得child的布局信息
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)child.getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicWidth();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    //由于Divider也有长宽高,每一个Item需要向下或者向右偏移
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if(mOrientation == HORIZONTAL_LIST){
            //画横线,就是往下偏移一个分割线的高度
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        }else {
            //画竖线,就是往右偏移一个分割线的宽度
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}

从上面的代码中,我们还通过系统属性来适应屏幕的横屏和竖屏,然后确定画横的,还是竖的Divider,其实在里面我们做了三件事,第一件是:获取到系统中的listDivider, 我们就是通过它在主题中去设置的,下面第(6)小点看一下代码就知道了。第二件事:就是找到我们需要添加Divider的位置,从onDraw方法中去找到,并将Divider添加进去。第三个是:得到Item的偏移量。


(5)看看我们的MainActivity.java
package com.study.wnw.recyclerviewdivider;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
    //定义RecyclerView
    private RecyclerView mRecyclerView = null;

    //定义一个List集合,用于存放RecyclerView中的每一个数据
    private List<String> mData = null;

    //定义一个Adapter
    private MyAdapter mAdapter; 

   //定义一个LinearLayoutManager
    private LinearLayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //RecyclerView三步曲+LayoutManager
        initView();
        initData();
        mAdapter = new MyAdapter(this,mData);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setAdapter(mAdapter); 

        //这句就是添加我们自定义的分隔线
        mRecyclerView.addItemDecoration(new MyDecoration(this, MyDecoration.VERTICAL_LIST));
    }

    //初始化View
    private void initView(){
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView = (RecyclerView)findViewById(R.id.recyclerview);
    }

    //初始化加载到RecyclerView中的数据, 我这里只是给每一个Item添加了String类型的数据
    private void initData(){
        mData = new ArrayList<String>();
        for (int i = 0; i < 20; i++){
            mData.add("Item" + i);
        }
    }
}

(6)分隔线Divider的drawable文件:divider.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#7b7a7a"/>
    <size android:height="1dp"/>
</shape>

我们在这里面,画了一个:rectangle, 给它填充颜色,还有高度,这样就搞定了,高度小,显示出来也是一条线:其实线的本质就是长方形。这里可以根据个人需要,画不同类型的divider


(7)在styles.xml的AppTheme中,设置listDivider为我们的divider.xml文件:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:listDivider">@drawable/divider</item>
</style>

这样,我们将系统的listDivider设置成我们自定义的divider. 还记得我们在MyDecoration中获取系统的listDivider这个属性吗,这样通过这个属性,我们就可以将我们的divider.xml文件和MyDecoration.java进行关联了。


到这里所有的工作就完成了,下面展示一下运行结果:



竖屏效果图


横屏效果图

经过几个小时的写作,终于搞定了,虽然仅仅是一个添加分隔线的功能,但是还是想尽可能的通过自己的语言去理解,去认知它的原理,这样做起来就简单多了。一开始的时候,我夜不知道怎么去用,也参考了别人写的文章,特别是鸿洋大神的:Android RecyclerView 使用完全解析 体验艺术般的控件, 写得特别的棒,从中也学到了一些知识。


好了,这篇文章暂时写到这里了,简单的介绍了一些RecyclerView分隔线的原理和添加方法,希望大家能够多多交流,过几天我会继续写下一篇文章,RecyclerView系列之(3):为RecyclerView添加下拉刷新和上拉加载的功能。最后还是要感谢大家,感谢这个平台,能够让我们一起交流,一切学习。




文/右眼皮的爱(简书作者)
原文链接:http://www.jianshu.com/p/4eff036360da
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
Android代码-让RecyclerViews之间的间隔线更加方便 Dividers Dividers is an Android library to easily create separators for your RecyclerViews. It supports a wide range of dividers from simple ones, that apply to all your items equally, to a system of selectors that apply different styles to each item. Screenshots Usage The easiest way to start using Dividers is to create a DividerItemDecoration with a layer and provide it to your RecyclerView as follows: // Create a drawable for your divider Drawable exampleDrawable = getResources().getDrawa 立即下载

相关推荐

RecyclerView列表添加间隔线

RecyclerView因为没有默认的列表项间隔线,此源码结合我的博客,为RecyclerView列表添加间隔线,源码中包括垂直列表的“水平方向的间隔线” 与 水平列表的“竖直方向的间隔线”。

RecyclerView添加分割线

RecyclerView 并没有 divider 属性,但是我们可以通过 RecyclerView 的 addItemDecoration() 来添加分割线,该方法参数为 RecyclerView.ItemDecoration。 介绍 当 RecyclerView 添加 ItemDecoration 后,RecyclerView 在绘制每个 item 的时候,会去绘制 decorator,也就是会调用 ItemDecoration 的 onDraw() 和 onDrawOver() 方法。 Recyc

Makenna's World 4618

LaTex的下载与安装(2024小白+windows系统)

本文主要介绍了Latex的下载与安装,还包括安装过程中遇到的小问题的解决。

m0_53096519的博客 2万+

了解RecyclerView的分割线

RecyclerView有自带的分割线,有时候自带分割线满足不了项目需要,随即参考网络其他大佬的文章,自己写一个万能分割线。列表或者表格,一个类满足!

NightRain的博客 1749

普源精电DHO系列示波器选购指南:从学生党到工程师的完整对比

本文深入评测普源精电DHO系列示波器,从DHO800到DHO4000各型号的核心参数、功能特点及适用场景进行全面对比,帮助学生党和工程师根据实际需求选择最佳型号。重点分析带宽、采样率、存储深度等关键指标,并提供实用的选购建议和进阶使用技巧,帮助用户充分发挥示波器性能。

weixin_30485379的博客 167

【技术解析】AlexNet——从ReLU到Dropout的深度学习关键突破

本文深入解析AlexNet在深度学习领域的关键突破,重点探讨了ReLU激活函数和Dropout技术的革命性应用。作为卷积神经网络的里程碑,AlexNet通过ReLU解决梯度消失问题,利用Dropout有效防止过拟合,为现代深度学习模型奠定了重要基础。这些创新技术至今仍在计算机视觉和自然语言处理等领域发挥重要作用。

weixin_33719619的博客 272

recyclerview放不同的布局_RecyclerView系列之(2):为RecyclerView添加分隔线

一. 理解ListView和RecyclerView中的ChildView在讲为Item加入分割线本质的前,先来介绍,认识一下ChildView,也就是平时我们用到的ListView,RecyclerView中的getChildAt(int position)这个返回的ChildView是哪一部分?到底是哪一部分呢?一开始的时候,我理解错了,但是经过下面两张图这么一比较,你就明白了:下面看代码的区...

weixin_39678089的博客 200

仿真每日一练 | 有限元模态分析详解

结构的振动一直是工业领域产品分析的重点,在振动的仿真分析中,模态分析是其最基本的分析类型,通过研究结构的固有频率和振型对产品的设计提供指导。2.2、在interaction模块,通过special->Spring,在各点之间分别创建弹簧单元,弹簧刚度为1000。2.1、在interaction模块,创建两个RP点,与两侧RP点各间隔100大小,如图3所示;其中M、K、C均为n*n的矩阵,s、x、v为n*1的矢量,n为系统自由度数量。3、在Assembly模块创建装配体,两点之间的距离为100,如图2所示;

ansysxuexizhe的博客 1655

Android 中为RecyclerView控件添加分隔线

在http://blog.youkuaiyun.com/hacker_zhidian/article/details/56292052这边文章中,我们看了一下ListView控件和RecyclerView控件的简单用法,那么下面我们将关注点放在RecyclerView上,毕竟RecyclerView控件在很多方面确实比ListView控件更好用。下面来看一下怎么对RecyclerView中的子项添加分隔线:

指点 5221

JavaSwing_4.2: JDialog、JOptionPane(对话框)

JDialog,对话框。使用 JDialog 类可以创建自定义有的对话框,或者调用 JOptionPane 中的多个静态方法快速创建各种标准的对话框。JOptionPane是 JavaSwing 内部已实现好的,以静态方法的形式提供调用,能够快速方便的弹出要求用户提供值或向其发出通知的标准对话框。

谢TS的博客 7万+

【WRF-Urban】使用 LCZ 替换 WRF 运行中的 LUCC 数据

使用 LCZ 替换 WRF 运行中的 LUCC 数据

WW、forever的博客 988

RecyclerView(三)——添加分隔线

RecyclerView中有一个默认的DividerItemDecoration,用于给RecyclerView添加分割线,实现方法如下recyclerView.addItemDecoration(new DividerItemDecoration(MainActivity.this));//setItemDecoration()方法用于为RecyclerView子项的一些装饰(我个人的理解)然后...

lans1996的博客 4777

Openai gym environment for multi-agent games

用于多智能体游戏的 OpenAI Gym 环境

suiusoar 1193

Android-给RecyclerView添加分隔线

RecyclerView和ListView不同 ,是不自带分隔线的如此:在讲为Item加入分割线本质的前,先来介绍,认识一下ChildView,也就是平时我们用到的ListViewRecyclerView中的getChildAt(int position)这个返回的ChildView是哪一部分?修改list_item的代码,添加一条 android:layout_margin = "10dp"Ch...

xiaofeng3011的博客 1412

专栏三:解析spatialCNV的使用

文章Spatially resolved clonal copy number alterations in benign and malignant tissue发在natur

m0_58549466的博客 1252

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

RecyclerView系列之添加分隔线

public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private LinearLayoutManager layoutManager; private MainAdapter mAdapter; private List<Stri...

Quincy.Coder的博客 326

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

为RecyclerView添加分隔线

1.原理篇分割线添加原理参照链接:https://www.jianshu.com/p/4eff036360da在RecyclerView中,Google又为我们提供了什么样的方法去添加分隔线呢?通过查看官方文档,它,提供了:addItemDecoration(RecyclerView.ItemDecoration decor)这个方法了设置分隔线,那问题又来了,RecyclerView.ItemD

lemonteazhang的博客 280

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

一起Talk Android吧(第四百四十回:如何给RecyclerView添加分隔线)

本章回中主要介绍了如何给RecyclerView添加分隔线,包含添加的步骤和示例代码。同时介绍了如何自定义分隔线。

talk_8的专栏 502

Android RecyclerView添加分隔线 DividerItemDecoration

RecyclerView的分隔线需要自定义设置 DividerItemDecoration 是一个官方的例子中的 mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.HORIZONTAL_LIST)); mRecyclerView.addItemDecoration

打渔还是晒网 —— stone 1万+

如何在RecyclerView中的项目之间添加分隔线和空格?

This is an example of how it could have been done previously in the ListView class, using the divid

w36680130的博客 546
上一篇: RecyclerView系列之(1):为RecyclerView添加Header和Footer
下一篇: JAVA面试基础1
AuthFailure
博客等级 码龄10年 0粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值