RecyclerView总结学习(二)

RecyclerView总结学习(二)

前言

上一篇学习了下RecyclerView的基本使用,主要是一些基本操作。回顾下:

RecyclerView 是Android L版本中新添加的一个用来取代ListView的SDK,它的灵活性与可替代性比listview更好.

首先还是POST出我的学习链接:
http://blog.csdn.net/lmj623565791/article/details/44014941
http://blog.csdn.net/lmj623565791/article/details/51118836
https://github.com/hongyangAndroid/base-adapter
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/1120/3705.html

要使用RecyclerView你需要做一些几件事情:
- 设置布局管理器LayoutManager,控制其显示的方式。
- 通过ItemDecoration来设置Item间的间隔。
- 通过ItemAnimator来设置Item间的增删动画。
- 自写RecyclerView.Adapter。

Adapter要自己来写,这多麻烦啊。还不像ListView可以使用多种适配器像ArrayAdapter、SimpleAdapter等等啊。RecyclerView还必须使用ViewHolder。但是总有大神会帮你解决这些问题的!

在RecyclerView没出来之前就有ListView的万能适配器了,既然RecyclerView相似,那么适配器上也可以有所借鉴了。

本文主要学习两种RecyclerView的万能适配器的使用,第一种是鸿洋老师写的万能适配器,第二种是陈宇明老师的万能适配器。从使用上来看陈宇明老师的适配器功能更加完善。本文只学习使用并不研究代码~

万能适配器(一)

使用方法

首先要使用鸿洋老师的万能适配器,你要在你的build.gradle中添加

    compile 'com.android.support:recyclerview-v7:23.2.0'//使用RecyclerView
    compile 'com.zhy:base-adapter:2.0.0'//使用万能适配器

对于简单的RecyclerView即从鸿洋老师的例子来看是只有一个ItemType的RecyclerView,比如下面这种形式统一的RecyclerView。

要实现上面的效果你只需要在完成以下几件事情:
- 数据封装,以及数据集的准备。
- 设置布局管理器和分割线,通过以下代码设置:

mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));

如果使用CardView的话可以不设置分割线…
- 完成item_list.xml的编写,这个就是RecylerView每一项的布局格式,本人测试的item_list.xml如下:

    
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_marginTop="10dp"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        <ImageView
            android:id="@+id/icon1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            />

        <TextView
            android:id="@+id/name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="li" />

        <TextView
            android:id="@+id/info1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            />
        LinearLayout>
android.support.v7.widget.CardView>
  • 使用万能适配器,代码如下:
recyclerView.setAdapter(new CommonAdapter(this, R.layout.item_list, mDatas) {
            @Override
            public void convert(ViewHolder holder, Persons persons) {
                holder.setText(R.id.name, persons.getName());
                holder.setText(R.id.info1, persons.getInfo());
                holder.setImageResource(R.id.icon1, persons.getIcon());
            }
        });

可以看到适配器这部分的代码确实简单了很多,以往还得自己写个Adapter,现在只要将数据和相应的视图对应就可以了。相当的方便。这样的话那些数据项是统一样式的RecyclerView就能够几句话完成适配了!

多个ItemViewTyped的RecyclerView

针对于多个ItemViewType的RecyclerView则可以通过MutiItemCommonAdapter来实现,比如鸿洋大神Sample里的聊天记录的展示。这个的代码实现就没有上面那么简单了,需要自己写一个适配器(这也是理所应当的,不然谁知道你哪种情况下需要使用哪种视图展示啊)。
其构造适配器的步骤如下:
- 首先你的数据集肯定是要考虑到这个点的,你可以在之前的数据集中设置一个布尔值。在适配的时候进行判断!(鸿洋老师的例子),当然你也可以设置多个数据集,分别对应不同的视图。
- 之后你就需要写RecyclerView的适配器了,继承自MultiItemCommonAdapter,在构造器中我们要告诉代码我们有几种当时的ItemType,设置好对应关系。
- 之后在convert()函数中完成数据项与视图的一一对应。

这个我个人感觉会用的不会很多,有很多问题我也没有问题研究。等到使用到这种方式的时候着重研究下,这里先记个笔记。

带Header的RecyclerView

第三种,添加Header。关于给RecyclerView添加Header的原理,请看第四篇学习博客,里面详细介绍了如何实现给RecyclerView添加Header。其实Header同样是作为RecyclerView的一个Item来考虑的,只是我们通过ItemType去找到它,如果是Header就设置HeaderView如果不是Header就正常设置Item。大致的原理就是这样。

在鸿洋老师的万能适配器中,封装好后你只需要按如下步骤做就可以了:

    SectionSupport sectionSupport = new SectionSupport()
{
    @Override
    public int sectionHeaderLayoutId()
    {
        return R.layout.header;
    }

    @Override
    public int sectionTitleTextViewId()
    {
        return R.id.id_header_title;
    }

    @Override
    public String getTitle(String s)
    {
        return s.substring(0, 1);
    }
};

在上面的代码中 首先指定Header的布局,以及布局中显示标题的TextView,以及根据Item显示什么样的标题。通过上面的 SectionSupport来指定。这里有一点需要注意的就是,标题栏里的标题是通过getTitle() 设置的,在鸿洋老师的例子中,鸿洋老师在initData()设置数据集的时候做了点手脚,就是每个数据就都是“A(B.C…) + 数字”,这样标题就取第一个字母就行了,但这里有两个问题不晓得是鸿洋老师例子中没有展示还是没有实现,一个是这里默认的标题是TextView,如果是要以ImageView作为标题呢?
第二个问题就是标题栏的标题设置有什么更好的办法吗?

在接下来就很简单了:

     SectionAdapter adapter = new SectionAdapter(this, R.layout.item_list, mDatas, sectionSupport)
        {

            @Override
            public void convert(ViewHolder holder, String s)
            {
                holder.setText(R.id.id_item_list_title, s);
            }
        };
        mRecyclerView.setAdapter(adapter);

这样就完成了Header的添加。最后是鸿洋老师Sample的展示。

万能适配器(二)

使用方法

学习完鸿洋老师的万能适配器的使用,接下来学习下陈宇明大神的万能适配器,就例子的功能和效果来看确实要比鸿洋老师更丰富一些。使用起来也很好,但我看陈大神github首页的介绍使用的时候没有鸿洋老师来的省力,因为陈大神把很多的数据封装起来了,所以光看他的Github介绍是无法了解如何使用的,必须把他的代码Clone或者DownLoad下来看看才知道如何使用。但总的来说陈大神的万能适配器还是很好使用的。

学习链接:
http://www.jianshu.com/p/411ab861034f
http://www.jianshu.com/p/fa3f97c19263
http://www.jianshu.com/p/9d75c22f0964
http://www.jianshu.com/p/cf29d4e45536
https://github.com/CymChad/BaseRecyclerViewAdapterHelper/blob/master/README-cn.md

因为陈大神的数据全部封装起来了,我这里就不用他的例子了,我自己学习了下如何使用后,自己实践了下!

首先还是数据集的创建:

public class Persons {

    private String name;
    private String info;
    private int icon;

    public Persons(String name, String info, int icon) {
        this.name = name;
        this.info = info;
        this.icon = icon;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public int getIcon() {
        return icon;
    }

    public void setIcon(int icon) {
        this.icon = icon;
    }

这就类似陈大神例子中的Status,然后我们就直接写QuickAdapter了。

public class QuickAdapter extends BaseQuickAdapter<Persons> {


    public QuickAdapter(int layoutResId, List data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder baseViewHolder, Persons persons) {
        baseViewHolder.setText(R.id.name, persons.getName());
        baseViewHolder.setText(R.id.info1, persons.getInfo());
        baseViewHolder.setImageResource(R.id.icon1, persons.getIcon());
        baseViewHolder.setOnClickListener(R.id.name, new OnItemChildClickListener());
//        baseViewHolder.setOnClickListener(R.id.info1, new OnItemChildClickListener());
        baseViewHolder.setOnClickListener(R.id.icon1, new OnItemChildClickListener());
    }
}

这个RecyclerView.Adapater基本类似,上面说的两个万能适配器都是参考
JoanZapata / base-adapter-helper
所以适配器的代码普遍相似。

然后就回到MainAcitivity中去:

public class MainActivity extends AppCompatActivity {

    private RecyclerView rv_list;
    private List mDatas = new ArrayList();
    private QuickAdapter mQuickAdapter;
    private static final String TAG = "MainActivity";

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

        initDatas();

        rv_list = (RecyclerView) findViewById(R.id.rv_list);
        rv_list.setLayoutManager(new LinearLayoutManager(this));
        mQuickAdapter = new QuickAdapter(R.layout.item_list, mDatas);

        //添加RecyclerView的点击事件
        mQuickAdapter.setOnRecyclerViewItemClickListener(new BaseQuickAdapter.OnRecyclerViewItemClickListener() {
            @Override
            public void onItemClick(View view, int i) {
                Toast.makeText(MainActivity.this, "Item" + i + "has been clicked", Toast.LENGTH_SHORT).show();
            }
        });
        //添加RecyclerView的长按事件
        mQuickAdapter.setOnRecyclerViewItemLongClickListener(new BaseQuickAdapter.OnRecyclerViewItemLongClickListener() {
            @Override
            public boolean onItemLongClick(View view, int i) {
                Toast.makeText(MainActivity.this, "长按", Toast.LENGTH_SHORT).show();
                return true;
            }
        });
        //添加RecyclerView的子布局多个控件的点击事件
        mQuickAdapter.setOnRecyclerViewItemChildClickListener(new BaseQuickAdapter.OnRecyclerViewItemChildClickListener() {
            @Override
            public void onItemChildClick(BaseQuickAdapter baseQuickAdapter, View view, int i) {
                switch (view.getId()){
                    case R.id.icon1:
                        Toast.makeText(MainActivity.this, "icon1" + i + "has been clicked", Toast.LENGTH_SHORT).show();
                        Log.d(TAG, "onItemChildClick: had been finished");
                        break;
                    case R.id.name:
                        Toast.makeText(MainActivity.this, "name" + i + "has been clicked", Toast.LENGTH_SHORT).show();
                        Log.d(TAG, "onItemChildClick: had been finished");
                        break;
                    case R.id.info1:
                        Toast.makeText(MainActivity.this, "info" + i + "has been clicked", Toast.LENGTH_SHORT).show();
                        Log.d(TAG, "onItemChildClick: had been finished");
                        break;
                }
            }
        });

        mQuickAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN);
        mQuickAdapter.isFirstOnly(false);
        rv_list.setAdapter(mQuickAdapter);
    }

    private void initDatas(){
        mDatas.add(new Persons("li", "qedasc6456qdsadas", R.drawable.ic_launcher));
        mDatas.add(new Persons("li2", "qedascqdsa6456das", R.drawable.ic_launcher));
        mDatas.add(new Persons("li3", "qed43asc754qdsadas", R.drawable.ic_launcher));
        mDatas.add(new Persons("li4", "qedascqdsadas", R.drawable.ic_launcher));
        mDatas.add(new Persons("li5", "qe43dascqd31sadas", R.drawable.ic_launcher));
        mDatas.add(new Persons("li6", "qedascqd1sad31as", R.drawable.ic_launcher));
        mDatas.add(new Persons("li7", "qedascqdsa12das", R.drawable.ic_launcher));
        mDatas.add(new Persons("li8", "qedascqdsa123das", R.drawable.ic_launcher));
        mDatas.add(new Persons("li9", "qedascqds321adas", R.drawable.ic_launcher));
        mDatas.add(new Persons("li10", "qedasc1231qdsadas", R.drawable.ic_launcher));
        mDatas.add(new Persons("li11", "qed3123cqdsadas", R.drawable.ic_launcher));
        mDatas.add(new Persons("li12", "qeewqdascqdsadas", R.drawable.ic_launcher));
        mDatas.add(new Persons("li13", "qedascqds23ss", R.drawable.ic_launcher));
        mDatas.add(new Persons("li14", "qedascqdsaas", R.drawable.ic_launcher));
    }
}

很简单,和鸿洋老师那个万能适配器做的事情一样。但这里有两个优点,第一个添加动画方面很方便,只需要一行代码就可以搞定
quickAdapter.openLoadAnimation();
不加参数的话就是默认的动画效果,其还提供其他五种效果

BaseQuickAdapter.ALPHAIN 渐显
BaseQuickAdapter.SCALEIN 缩放
BaseQuickAdapter.SLIDEIN_BOTTOM 从下到上滑进
BaseQuickAdapter.SLIDEIN_LEFT 从左到右滑进
BaseQuickAdapter.SLIDEIN_RIGHT 从右到左滑进

第二个能够添加子布局多个控件的点击事件,这个功能应该比长按功能更来得实际。要实现也很简单:

首先在你写的Adapter中,这里即QuickAdapter中添加控件的点击事件即可:

 protected void convert(BaseViewHolder helper, Status item) {
    helper.setOnClickListener(R.id.tweetAvatar, new OnItemChildClickListener())
      .setOnClickListener(R.id.tweetName, new OnItemChildClickListener());
      }

然后在Activity中实现子布局的控件的点击事件:

 mQuickAdapter.setOnRecyclerViewItemChildClickListener(new BaseQuickAdapter.OnRecyclerViewItemChildClickListener() {
            @Override
            public void onItemChildClick(BaseQuickAdapter baseQuickAdapter, View view, int i) {
                switch (view.getId()){
                    case R.id.icon1:
                        Toast.makeText(MainActivity.this, "icon1" + i + "has been clicked", Toast.LENGTH_SHORT).show();
                        Log.d(TAG, "onItemChildClick: had been finished");
                        break;
                    case R.id.name:
                        Toast.makeText(MainActivity.this, "name" + i + "has been clicked", Toast.LENGTH_SHORT).show();
                        Log.d(TAG, "onItemChildClick: had been finished");
                        break;
                    case R.id.info1:
                        Toast.makeText(MainActivity.this, "info" + i + "has been clicked", Toast.LENGTH_SHORT).show();
                        Log.d(TAG, "onItemChildClick: had been finished");
                        break;
                }
            }
        });

是不是特别简单,这样感觉QQ都能自己写了呢~(开个玩笑)最后的效果如下:

多个ItemViewTyped的RecyclerView

接着就是多个ItemViewType的RecyclerView的使用了,实话实说,在这个方面的使用上来讲,陈大神的万能适配器真的比鸿洋老师的好用不少,还记得鸿洋老师的如何使用吗…回顾下:
- 首先你的数据集得多一个变量,作用是做判断是哪种ItemType
- 接着在Adapter里你就是对变量进行判断然后对应其ItemType
- 再接着就是每种ItemType对应一个布局了。

而陈大神的万能适配器的具体使用步骤如下:

  • 首先也是需要一个数据集的,当然这个数据集也得给出ItemType,但不需要多余的变量来进行判断。这里需要注意的是这个数据集必须继承自MultiItemEntity,因为它提供了一个setItemType的方法,去设置每个数据的ItemType
  • 再来就是编写Adapter了,这个适配器得继承自BaseMultiItemQuickAdapter,这里重载实现convert()方法。

说的太虚又说不准,拿例子来说话吧。
第一步数据集的构造:

    public class MutiItem extends MultiItemEntity {
    public static final int SEND = 1;
    public static final int FROM = 2;

    private int icon;
    private String name;
    private String content;
    private String createDate;


    public MutiItem(int icon, String name, String content, String createDate) {
        this.name = name;
        this.icon = icon;
        this.content = content;
        this.createDate = createDate;
    }

    public int getIcon() {
        return icon;
    }

    public void setIcon(int icon) {
        this.icon = icon;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getCreateDate() {
        return createDate;
    }

    public void setCreateDate(String createDate) {
        this.createDate = createDate;
    }
}

这里我直接把鸿洋老师的ChatMessage去了一个变量后直接拿来用了

前面两个常量就是ItemType。而Adapter就更简单了。只需要设置ItemType对应的视图,以及convert里做数据填充就可以了。

    public class MutiItemAdapter extends BaseMultiItemQuickAdapter<MutiItem> {


    public MutiItemAdapter(Context context, List data) {
        super(data);
        addItemType(MutiItem.SEND, R.layout.main_chat_send_msg);
        addItemType(MutiItem.FROM, R.layout.main_chat_from_msg);
    }

    @Override
    protected void convert(BaseViewHolder baseViewHolder, MutiItem mutiItem) {
        switch (baseViewHolder.getItemViewType()) {
            case MutiItem.SEND:
                baseViewHolder.setText(R.id.chat_send_content, mutiItem.getContent());
                baseViewHolder.setText(R.id.chat_send_name, mutiItem.getName());
                baseViewHolder.setImageResource(R.id.chat_send_icon, mutiItem.getIcon());
                break;
            case MutiItem.FROM:
                baseViewHolder.setText(R.id.chat_from_content, mutiItem.getContent());
                baseViewHolder.setText(R.id.chat_from_name, mutiItem.getName());
                baseViewHolder.setImageResource(R.id.chat_from_icon, mutiItem.getIcon());
                break;

        }
    }
}

然后就可以在Activity中设置RecyclerView的Adapter了。

    public class MutiItemActivity extends Activity {
    private RecyclerView mRecyclerView;
    private List mutiItemList = new ArrayList();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.mutiitem);
        mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        initData();
        MutiItemAdapter mutiItemAdapter = new MutiItemAdapter(this, mutiItemList);
        mRecyclerView.setAdapter(mutiItemAdapter);

    }

    private void initData(){
        MutiItem item = null;
        item =  new MutiItem(R.drawable.xiaohei, "xiaohei", "where are you ", null);
        item.setItemType(MutiItem.SEND);
        mutiItemList.add(item);
        item =  new MutiItem(R.drawable.xiaohei, "renma", "where are you ", null);
        item.setItemType(MutiItem.FROM);
        mutiItemList.add(item);
        item =  new MutiItem(R.drawable.xiaohei, "xiaohei", "where are you ", null);
        item.setItemType(MutiItem.SEND);
        mutiItemList.add(item);
        item =  new MutiItem(R.drawable.xiaohei, "renma", "where are you ", null);
        item.setItemType(MutiItem.FROM);
        mutiItemList.add(item);
        item =  new MutiItem(R.drawable.xiaohei, "xiaohei", "where are you ", null);
        item.setItemType(MutiItem.SEND);
        mutiItemList.add(item);
        item =  new MutiItem(R.drawable.xiaohei, "xiaohei", "where are you ", null);
        item.setItemType(MutiItem.SEND);
        mutiItemList.add(item);
        item =  new MutiItem(R.drawable.xiaohei, "renma", "where are you ", null);
        item.setItemType(MutiItem.FROM);
        mutiItemList.add(item);
        item =  new MutiItem(R.drawable.xiaohei, "xiaohei", "where are you ", null);
        item.setItemType(MutiItem.SEND);
        mutiItemList.add(item);
        item =  new MutiItem(R.drawable.xiaohei, "renma", "where are you ", null);
        item.setItemType(MutiItem.FROM);
        mutiItemList.add(item);
        item =  new MutiItem(R.drawable.xiaohei, "xiaohei", "where are you ", null);
        item.setItemType(MutiItem.SEND);
        mutiItemList.add(item);


    }
}

是不是超级简单,只是别忘了在数据构造的时候记得使用setItemType

带Header的RecyclerView

根据官方的介绍,要添加HeaderView和FooterView,只需要两句代码就可以搞定。

mQuickAdapter.addHeaderView(getView());
mQuickAdapter.addFooterView(getView());

这里的getView()返回的是一个View.

如果只有一个HeaderView和FooterView那这个万能适配器就能完美实现,但像鸿洋老师那种可以添加多个HeaderView的,这边没有提及。但也不是没有解决办法,添加Header的思想其实也就是多加一个ItemType,如果真要实现分类,有多个Header的话,那就把HeaderView作为一个ItemType,指定其视图就好了~

你可能感兴趣的:(Android学习)