RecyclerView

简介

概述

Android 5.0 新推出了RecyclerView组件,是ListView和GridView的替代方案。通过导入support-v7包进行使用,最低向前兼容到3.0。据官方的介绍,该控件用于在有限的窗口中展示大量数据集。

A flexible view for providing a limited window into a large data set.

优缺点

既然已经有了使用很久的ListView和GridView,为什么还要提出这个呢?

  • 插拔式设计做到了高内聚低耦合。通过组合LayoutManager、ItemDecoration灵活实现各种效果。
  • 标准化了ViewHolder。强制使用ViewHolder机制,简化了编写任务。
  • 简单页面,不如ListView效率高。
  • 添加头部首部较麻烦。

既然RecyclerView这么好,那就赶紧用起来吧?!向大家推荐一些教程,看完再继续也不迟。这些都是个人看过,认为入门较好的内容。强烈安利!相关连接在文末参考文献中前2个。

基本使用

实现列表布局

RecyclerView的使用主要有以下5步:
1,Activity初始化布局,绑定控件;
2,写item布局;
3,创建Adapter;
3.1 写ViewHolder内部类;
3.2 继承Adapter并添加泛型;
3.3 覆写Adapter方法;
4,布局管理器绑定;
5,绑定适配器。

Activity.class示例如下:

public class MainActivity extends AppCompatActivity {
    //1. 初始化RecyclerView。
    //2. 创建Item布局。例如:item_rvmain.xml布局。
    RecyclerView mRecyclerView;
    Class[] mClass = new Class[]{GridActivity.class, GridActivity.class, FallsActivity.class};
    List<Class> mList;
    RecyclerView.Adapter mAdapter;

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

        initDate();
        mRecyclerView = findViewById(R.id.rv_main);
        RecyclerView.LayoutManager manager = new LinearLayoutManager(this);
        mAdapter = new MainAdapter(this, mList);
        mRecyclerView.setLayoutManager(manager);
        mRecyclerView.setAdapter(mAdapter);
    }

    private void initDate() {
        mList = Arrays.asList(mClass);
    }
}

MainAdapter.class示例如下:

//3. 创建Adapter。
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.MainHolder> {
    //3.2 获取基本数据。
    private Context mContext;
    private List<Class> mDate;

    protected MainAdapter(Context context, List<Class> date) {
        mContext = context;
        mDate = date;
    }

    //3.3 覆写相关方法。
    @NonNull
    @Override
    public MainHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.item_rvmain, parent, false);
        return new MainHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MainHolder holder, int position) {
        final Class clazz = mDate.get(position);
        holder.mTextView.setText(clazz.getSimpleName());
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(mContext, clazz);
                mContext.startActivity(intent);
            }
        });
    }

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

    //3.1 创建ViewHolder。
    class MainHolder extends RecyclerView.ViewHolder {
        TextView mTextView;

        public MainHolder(View itemView) {
            super(itemView);
            mTextView = itemView.findViewById(R.id.tv_main_item);
        }
    }
}

RecyclerView Base

LayoutManager

Recyclerview在设计时,将Item的布局方式抽象出来,降低了View和布局管理器的耦合度,通过设置不同的管理器灵活的实现不同布局效果。

RecyclerView.LayoutManager的具体实现类有三个:线性布局管理器LinearLayoutManager,网格布局管理器GridLayoutManager,瀑布流布局管理器StaggeredGridLayoutManager

相信聪明的你已经想到了,当需要特殊布局时,只需要模拟这三个通过自定义LayoutManager,就可以随心所欲了。

GridLayoutManager

假如,你使用列表布局开发完了。突然XX产品来说:“列表的太普通了,改成网格的吧,突出我们的产品特色!”如果用的ListView相信你已经端起了显示器,但是!用了Recyclerview,我们就可以微笑的告诉XX:“幸亏老子聪明!”。

这里写图片描述

实现网格布局,只需要更改LayoutManager的类型就可以了。真的只改下面这一点代码:

RecyclerView.LayoutManager manager = new GridLayoutManager(this, 3);

具体代码参照示例中:GridActivity。

StaggeredGridLayoutManager

和网格布局一样潇洒!瀑布流布局也是so easy!只需要更改布局管理器,并在Adapter中动态设置Item的大小。

FallsStringAdapter.java

//1. 修改LayoutManager。
RecyclerView.LayoutManager manager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
//2. Adapter中动态设置大小。例如:
ViewGroup.LayoutParams params = holder.mTextView.getLayoutParams();
Random random = new Random();
params.height = random.nextInt(30) + 70;
params.width = params.width;
holder.mTextView.setLayoutParams(params);

具体代码参照示例中:FallsActivity。

ItemDecoration分割线

实现了三种常见效果后,相信你已经发现问题了,Item间怎么没有分割线?这也是设计时功能解耦导致的。官方将分割线的功能解耦到了RecyclerView.ItemDecoration中,最开始官方只提供了此抽象类,由于需求很常见就把v7 samples中的DividerItemDecoration添加到v7.widget包下。

DividerItemDecoration

使用DividerItemDecoration添加分割线也很简单,记得它支持LinearLayoutManager布局方式的布局:

RecyclerView.ItemDecoration divider = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(divider);

自定义ItemDecoration

当网格布局和瀑布流布局时,就需要通过自定义来实现了。首先来分析ItemDecoration。主要有四个方法。当RecyclerView在绘制的时候,去会绘制decorator,即调用该类的onDraw和onDrawOver方法:

  • onDraw()先于drawChildren
  • onDrawOver()在drawChildren之后,这两个方法一般选择复写其中一个即可。
  • getItemOffsets 可以通过outRect.set()为每个Item设置一定的偏移量,主要用于绘制Decorator。

下面分析下,DividerItemDecoration的具体实现:

  1. 通过读取系统主题中的android.R.attr.listDivider作为Item间的分割线,值是个Drawable。
  2. getItemOffsets()中,outRect去设置了绘制的范围。
  3. onDraw()中实现了真正的绘制。

Theme方式自定义颜色

获取系统的android.R.attr.listDivider的优点就是。我们可以通过设置系统主题灵活的变更分割线颜色。例如:
在styles.xml文件中,增加style:

<style name="DividerTheme" parent="AppTheme">
	<item name="android:listDivider">@drawable/base_divider_bg</item>
</style>

在brawable中新建一个base_divider_bg.xml:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <gradient
        android:centerColor="#ff00ff00"
        android:endColor="#ff0000ff"
        android:startColor="#ffff0000"
        android:type="linear" />
    <size android:height="4dp"/>

</shape>

在AndroidManifest.xml中,全局或者某个Activity中指定此样式即可:

<!-- 此是作用在整个应用中 -->   
<application
	android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"        
    android:theme="@style/DividerTheme"> 
...
<!-- 此是作用在DividerThemeActivity中 --> 
	<activity android:name=".divider.DividerThemeActivity"
	    android:theme="@style/DividerTheme"
	    ></activity>
</application>

ColorDivider
色彩骚不骚?

网格类布局分割线

当网格布局或瀑布流布局时分割线怎么办呢?当然自定义了啊!

其他方法实现分割线

机制的小伙伴们也想出了其他一些骚操作来实现分割线效果。但都没有自定义Item完善,但也算是脑洞大开的想法吧。

Item中加控件
此种方法是,在Item布局中添加控件来实现效果,记得在Adapter中隐藏最后一个。

此方法看似简单,但增加了Item布局的复杂性,影响新能。不建议如此实现。

头部
不能像ListView快速添加头部。

资源

中阶

错误

IllegalStateException: RecyclerView has no LayoutManager
此错误。发生原因:由于RecyclerView没有布局管理器,而在item的布局中触发了错误。
一般是:在RecyclerView中添加了View。

正确删除操作

BRVAH实践

优点

缺点

实际场景

  1. item的图片右上方有删除操作。其他方案:a,接口回调。在Adapter中添加监听接口。在逻辑中,回调接口。BRVAH:在Adapter中添加监听方法,在逻辑中为Adapter设置setOnItemChildClickListener();

参考文献

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值