Android开发学习之RecyclerView+CardView的使用

介绍

RecyclerView是一种高级的ListView,以后可以用它来代替ListView

CardView则是一种更好看的视图,使用比较简单,这里我把他俩放在一起介绍

基本使用步骤

导入依赖

我们得先导入RecyclerView和CardView的依赖

compile 'com.android.support:recyclerview-v7:26.0.0'
compile 'com.android.support:cardview-v7:26.0.0'
//recyclerView和cardView库


在主布局中加入RecyclerView

在activity_main.xml中加入RecyclerView

<android.support.v7.widget.RecyclerView
  android:id="@+id/rv_recycler"
  android:layout_width="match_parent"
  android:layout_height="wrap_content">

</android.support.v7.widget.RecyclerView>

用法其实跟listView差不多


创建item的布局

为RecyclerView的子项创建布局,名之为iterm.recycler.xml

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto" <!-- 注意cardView的命名空间 -->
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    card_view:cardCornerRadius="4dp" <!-- 设置卡片四个角的弧度半径 -->
    android:layout_margin="10dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="90dp"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/iv_img"
            android:layout_weight="1"
            android:layout_width="90dp"
            android:gravity="center"
            android:layout_height="match_parent" />
        <TextView
            android:id="@+id/tv_img"
            android:layout_weight="1"
            android:layout_width="50dp"
            android:gravity="center"
            android:layout_height="match_parent" />

        <Button
            android:id="@+id/btn_img"
            android:text="这是哪个队"
            android:gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="match_parent" />
    </LinearLayout>



</android.support.v7.widget.CardView>
为了好看我用了CardView做为子项的根布局,注意它的用法,参加注释


在MainActivity中设置RecyclerView

@BindView(R.id.rv_recycler)
RecyclerView recyclerView;

@Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activty_main);
    ButterKnife.bind(this);

    recyclerView.setLayoutManager(new LinearLayoutManager(this)); // 设置线性布局

    ...
}

我使用了ButterKnife来初始化控件(其实就是findViewById()),现在先不管他,以后再介绍用法

通过recyclerView.setLayoutManager()可以指定recyclerView是哪种布局,这里我直接使用线性布局


构造Adapter类

RecyclerView跟ListView一样,也需要适配器。这里我们写一个适配器类,继承RecyclerView.Adapter

public class AdapterForRecyclerVIew extends RecyclerView.Adapter {
    private LinkedList<String> urls = new LinkedList<>();
    private LinkedList<String> descriptions = new LinkedList<>();
    private Context context = null;

    private String TAG = "AdapterForRecyclerVIew";

    public AdapterForRecyclerVIew(LinkedList<String> urls,LinkedList<String> descriptions, Context context) {
        this.urls = urls;
        this.descriptions = descriptions;
        this.context = context;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
       CardView layout = (CardView) LayoutInflater.from(context).inflate(R.layout.item_recycler, parent, false); // 要inflate子项的根节点 carView
       return new MyViewHolderForImage(layout);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
       MyViewHolderForImage holderForImage = (MyViewHolderForImage) holder;
       Picasso.with(context).load(urls.get(position - 1)).into(holderForImage.getImageView());
       holderForImage.getTextView().setText(descriptions.get(position - 1));
    }

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

里面的三个方法onCreateViewHolder()、onBindViewHolder()、getItemCount()都是我们必须要实现的。

其中onCreateViewHolder()用来创建子项的viewHolder,所以我们要新建一个ViewHolder类,继承RecyclerView.ViewHolder,这个ViewHolder里面就是子项的所有控件,子项的UI逻辑,都放在ViewHolder中,可以作为mvp设计模式中的presenter(代码下一步再说)

onBindViewHolder()则是加载子项viewHolder的内容,参数里面的holder就是上一个方法onCreateViewHolder()中返回过来的

getItemCount()方法决定了recyclerView要显示多少个子项


创建ViewHolder类

根据上一步说的,我们把子项逻辑都放在ViewHolder中

public class MyViewHolderForImage extends RecyclerView.ViewHolder {
    @BindView(R.id.iv_img) ImageView imageView;
    @BindView(R.id.tv_img) TextView textView;
    public MyViewHolderForImage(View itemView) {
        super(itemView);
        ButterKnife.bind(this,itemView); // 根据adapter中的onCreateViewHolder(),这里传进来的itermView就是cardView
        textView.setVisibility(View.INVISIBLE);
    }

    @OnClick(R.id.btn_img)
    public void changeVisibility(){
        textView.setVisibility(View.VISIBLE);
    }

    public ImageView getImageView() {
        return imageView;
    }

    public TextView getTextView() {
        return textView;
    }
}

还是用了ButterKnife绑定控件,设置onClick监听


为recyclerView设置adapter,并初始化数据

回到onCreate(),设置一下adapter,并赋予一些数据

adapter = new AdapterForRecyclerVIew(urls, descriptions, this);

addUrls();
addDescriptions();

recyclerView.setAdapter(adapter);
private void addDescriptions() {
    descriptions.add("南部之星拜仁慕尼黑");
    descriptions.add("骄傲的大黄蜂多特蒙德");
    descriptions.add("红魔曼联");
    descriptions.add("蓝军切尔西");
}

private void addUrls() {
    urls.add("http://n.sinaimg.cn/sports/transform/20170216/1s3V-fyarzzv2801842.jpg");
    urls.add("http://www.zq1.com/Upload/20170415/235459msc9i5yiqracirfw.jpg");
    urls.add("http://k.sinaimg.cn/n/sports/transform/20160424/dfCS-fxrqhar9877773.JPG/w570fe9.jpg");
    urls.add("http://n.sinaimg.cn/sports/transform/20170423/L9Uj-fyeqcac1387497.jpg");
}

由于我是先设置数据,再设置适配,所以不用notifyDataSetChanged()


效果

ok,这就是recyclerView的基本用法


多种类型子项混排

可以看到,在录屏gif种,最上面最下面是文字,而这些文字也是RecyclerView的子项,怎么实现呢?只需要增加相应子项的布局文件和对应ViewHolder、再改变一下adapter就行

添加新子项的xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_item"
        android:gravity="center"
        android:layout_gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>


添加新子项的viewHolder

public class MyViewHolderForText extends RecyclerView.ViewHolder {
    @BindView(R.id.tv_item) TextView textView;

    public MyViewHolderForText(View itemView) {
        super(itemView);
        ButterKnife.bind(this,itemView);
    }

    public TextView getTextView() {
        return textView;
    }
}


更改adapter

添加子项类型枚举

因为有多种子项,为了鉴别,我们最好定义一种枚举,来区分子项类型

private enum viewType {
    TYPE_TEXT, TYPE_IMAGE;
}


覆写getItemViewType方法

为了获取子项类型,我们需要覆写父类种getItemViewType()方法

@Override
public int getItemViewType(int position) {
    if (position == 0 || position == urls.size() + 1) {
        return viewType.TYPE_TEXT.ordinal();
    }
    return viewType.TYPE_IMAGE.ordinal();
}


修改getItemCount方法

这时我们要多显示两项,所以返回值要+2

@Override
public int getItemCount() {
    return urls.size() + 2;
}


修改onCreateViewHolder方法和onBindViewHolder方法

根据viewType来获取不同的viewHolder或执行不同逻辑

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == AdapterForRecyclerVIew.viewType.TYPE_IMAGE.ordinal()) {
         CardView layout = (CardView) LayoutInflater.from(context).inflate(R.layout.item_recycler, parent, false);
         return new MyViewHolderForImage(layout);
    } else {
         LinearLayout layout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.text_item_recycler, parent, false);
         return new MyViewHolderForText(layout);
    }
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (holder.getItemViewType() == viewType.TYPE_IMAGE.ordinal()) {
       MyViewHolderForImage holderForImage = (MyViewHolderForImage) holder;
       Picasso.with(context).load(urls.get(position - 1)).into(holderForImage.getImageView()); // 因为第一个是textView,所以url的索引是position-1
       holderForImage.getTextView().setText(descriptions.get(position - 1));
    } else {
       ((MyViewHolderForText) holder).getTextView().setText("宋泽嶒");
    }
}

这样,就大功告成了


结语

RecyclerView可以帮助我们更好地实现mvp,也是一种性能更好的listView

猜你喜欢

转载自blog.csdn.net/qq_37475168/article/details/80106632
今日推荐