RecyclerView多布局的简单使用

时间:2024-04-08 12:55:01

RecyclerView多布局的简单

   RecyclerView 是在Android5.0之后推出的,是一个比ListView更加灵活更加高效的适配器类型控件。但是RecyclerView不同于其他类型的适配器,它还需要一个LayoutManager进行页面控制展示。RecyclerView提供了三种布局管理器:
  1、LinearLayoutManager:线性布局管理器,支持水平和垂直效果。
  2、GridLayoutManager:网格布局管理器,支持水平和垂直效果。
  3、StaggeredGridLayoutManager:分布型管理器,瀑布流效果

RecyclerView的使用:
  1、引入RecyclerView依赖包,V7下的,兼容到API17.
  2、在xml布局中声明,在Java代码中初始化。
  3、设置布局管理器
  4、创建适配器,设置数据源,绑定适配器
    具体创建适配器:①创建一个类,继承RecyclerView.Adapter<ViewHolder>.
            ②创建一个类ViewHolder,继承RecyclerView。VIewHolder,该类需要创建一个匹配父类的构造。
            ③重写适配器中的方法:getItemCount():获取数据源的个数(item的数量);onCreateViewHolder():该方法中导入布局,实例化VIewHolder;onBindViewHolder():绑定VIewHolder,加载数据。

注意一点:RecyclerView的LinearLayoutManager不同于一般的适配器的布局,RecyclerView的item最外层的布局参数是有效的,如高度宽度等,所以在使用的时候,第一种方法是在导入View的时候指定没有parent(不推荐使用),第二种方法是在item布局的最外层指定具体的参数。
RecyclerView 为开发者提供了强大的复用机制,但是所有的点击事件都丢了,没有提供默认的点击事件,所以需要我们自己为RecyclerView手动实现点击。

 

多布局在JSON文件中一般有明确的区分,例如通过Type=1,2,3,4,等方式进行区分,Type=1,说明是一种类型的布局!

RecyclerView的使用场景:

多种样式的列表。

宫格和列表同时存在

分类列表(比如通讯录)

RecyclerView多布局的简单使用RecyclerView多布局的简单使用

多布局的重点:

1、       复写getItemViewType(int position)

根据各个position的位置,返回不同的类型。

2、       处理getItemCount

3、       按照返回的类型处理onCreateViewHolder和onBindViewHolder方法

RecyclerView多种布局原理和机制::

     多种布局保存!

RV中的关键成员:

     Type <-   getItemViewType(int position)

     RecyclerView.Holder

     RecyclerView.Recycler

Recycler中保存了一些缓存机制(类上与ListView中的conVertView)

多布局的设计流程

滚动 ----àgetItemViewType(position)------à根据Type寻找Holder-------àif(寻找Holder时返回null)-----àadpter.createViewHolder-----à否则adapter.bindViewHolder.

getItemViewType

     ItemType保存在Holder中

     Holder根据position被缓存在cache中

     遍历缓存中的Holder,如果Type一致就返回。

当我们需要重复使用的时候,系统会在cache里面拿holder,进而实现使用流畅。

和ListView的区别

1.   type已经是Holder的成员

2.   RecyclerView的缓存单位是Holder而不在是View

3.   RecyclerPool的缓存key是type

getItemViewtype(intposition)中的Type,只需要一个数字,不一定是连续的数字。

 

    

     代码实现以及说明:

导入compile 'com.android.support:recyclerview-v7:26.+'

RecyclerView的依赖

DataModle:

   package com.example.jash.recyclerview_more;

import java.io.Serializable;
public class DataModel implements Serializable {
    public static final int TYPE_ONE = 1;
    public static final int TYPE_TWO = 2;
    public static final int TYPE_THREE = 3;
    public int type;
    public int avatarColor;
    public String name;
    public String Content;
    public int contentColor;
}
 
三个布局的XML:
First:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:gravity="center"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/avatar"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginLeft="20dp" />

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        tools:text="aaaaa" />
</LinearLayout>
Two:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:gravity="center"
    android:orientation="horizontal">
    <ImageView
        android:id="@+id/zuozhe"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginLeft="20dp" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            tools:text="aaaaa" />

        <TextView
            android:id="@+id/content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="10dp"
            tools:text="aaaaa" />
    </LinearLayout>
</LinearLayout>
Three:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="60dp">

    <ImageView
        android:layout_alignParentLeft="true"
        android:id="@+id/avatar"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_centerVertical="true" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@+id/avatar"
        android:orientation="vertical">

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            tools:text="aaaaa" />

        <TextView
            android:id="@+id/content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="10dp"
            tools:text="aaaaa" />
    </LinearLayout>

    <ImageView
        android:id="@+id/contentImage"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"/>
</RelativeLayout>
    抽象ViewHolder
import android.support.v7.widget.RecyclerView;
import android.view.View;
public abstract class TypeAbstrHolder extends RecyclerView.ViewHolder {

    public TypeAbstrHolder(View itemView) {
        super(itemView);
    }
    public abstract void bindHolder(DataModel model);
}
三个ViewHolder 继承抽象ViewHolder
First:
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
public class TypeOneViewHolder extends TypeAbstrHolder {
    public ImageView avatar;
    public TextView name;

    public TypeOneViewHolder(View itemView) {
        super(itemView);
        avatar = (ImageView) itemView.findViewById(R.id.avatar);
        name = (TextView) itemView.findViewById(R.id.name);
        itemView.setBackgroundColor(Color.GREEN);
    }

    @Override
    public void bindHolder(DataModel model) {
        avatar.setBackgroundResource(model.avatarColor);
        name.setText(model.name);
    }

}
Two:
import android.content.Context;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
public class TypeTwoHolder extends TypeAbstrHolder {
    private ImageView zuozhe;
    private TextView name;
    private TextView content;

    public TypeTwoHolder(View itemView) {
        super(itemView);
        zuozhe = (ImageView) itemView.findViewById(R.id.zuozhe);
        name = (TextView) itemView.findViewById(R.id.name);
        content = (TextView) itemView.findViewById(R.id.content);
        itemView.setBackgroundColor(Color.BLACK);
    }

    @Override
    public void bindHolder(DataModel model) {
        zuozhe.setBackgroundResource(model.avatarColor);
        name.setText(model.name);
        content.setText(model.Content);
    }
}
three:
import android.graphics.Color;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
public class TypeThreeViewHolder extends TypeAbstrHolder {
    private ImageView avatar;
    private TextView name;
    private TextView content;
    private ImageView contentColor;

    public TypeThreeViewHolder(View itemView) {
        super(itemView);
        avatar = (ImageView) itemView.findViewById(R.id.avatar);
        name = (TextView) itemView.findViewById(R.id.name);
        content = (TextView) itemView.findViewById(R.id.content);
        contentColor = (ImageView) itemView.findViewById(R.id.contentImage);
        itemView.setBackgroundColor(Color.GRAY);
    }

    @Override
    public void bindHolder(DataModel model) {
        avatar.setImageResource(model.avatarColor);
        name.setText(model.name);
        content.setText(model.Content);
        contentColor.setBackgroundResource(model.contentColor);
    }
}
RecyclerView的Adapter
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context context;
    private List<DataModel> mList = new ArrayList<>();
    private LayoutInflater inflater;

    protected MyAdapter(Context context) {
        this.context = context;
        inflater = LayoutInflater.from(context);
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType) {
            case DataModel.TYPE_ONE:
                return new TypeOneViewHolder(inflater.inflate(R.layout.one, parent, false));
            case DataModel.TYPE_TWO:
                return new TypeTwoHolder(inflater.inflate(R.layout.two, parent, false));
            case DataModel.TYPE_THREE:
                return new TypeThreeViewHolder(inflater.inflate(R.layout.three, parent, false));
        }
        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ((TypeAbstrHolder) holder).bindHolder(mList.get(position));
    }

    @Override
    public int getItemViewType(int position) {

        return mList.get(position).type;
    }

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

    public void addList(List<DataModel> list) {
        mList.addAll(list);
    }
}
MainActivity:
package com.example.jash.recyclerview_more;

import android.graphics.Rect;
import android.support.v4.view.GravityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private RecyclerView mRecycler;
    private MyAdapter mAdapter;
    int color[] = {android.R.color.holo_orange_dark,
            android.R.color.holo_red_dark,
            android.R.color.holo_blue_bright};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecycler = (RecyclerView) findViewById(R.id.recycler);
        mRecycler.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
        mAdapter = new MyAdapter(this);
        mRecycler.setAdapter(mAdapter);
        initData();
    }

    private void initData() {
        List<DataModel> list = new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            int type;
            if (i < 5 || (i > 15 && i < 20)) {
                type = 1;
            } else if (i < 10 || i > 26) {
                type = 2;
            } else {
                type = 3;
            }

            Log.d("1", "initData: " + String.valueOf(type) + "=====>>>" + i);
            DataModel data = new DataModel();
            data.avatarColor = color[type - 1];
            data.type = type;
            data.name = "name" + i;
            data.Content = "conten" + type;
            data.contentColor = color[type - 1];
            list.add(data);
        }
        mAdapter.addList(list);
    }
}
mainXML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context="com.example.jash.recyclerview_more.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>
实现的布局!
为列表类的还有三种不同的布局的显示
          
二、如何实现GridView和ListView同时显示!
    MainActivity中:加入代码
final GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);创建一个3列显示的GridView。 
        Log.d("1", "onCreate: " + gridLayoutManager.getSpanCount());
该方法为合并GridView中的列
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
//获取指定position上的itemView的type
                int type = mRecycler.getAdapter().getItemViewType(position);
//如果type==类型为3 的布局 
                if (type == DataModel.TYPE_THREE) {
//获取gridLayoutManager的列数,上面指定为3了,所有将3 合并成1,否则不合并
                    return gridLayoutManager.getSpanCount();
                } else {
                    return 1;
                }
            }
        });
//添加分隔线!
        mRecycler.addItemDecoration(new RecyclerView.ItemDecoration() {
            @Override
            public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
                GridLayoutManager.LayoutParams layoutParams = (GridLayoutManager.LayoutParams) view.getLayoutParams();
//获取一行中含有多少个 View
                int spanSize = layoutParams.getSpanSize();
// spanIndex ==1   为View的左侧  ==2  为View的右侧
                int spanIndex = layoutParams.getSpanIndex();
                outRect.top = 20;
                if (spanSize != gridLayoutManager.getSpanCount()) {
                   outRect.left=3;
                }
//切记一定要注释掉这行代码!
//                super.getItemOffsets(outRect, view, parent, state);
            }
        });
 
效果图:

             RecyclerView多布局的简单使用RecyclerView多布局的简单使用