Android Studio开发学习(六)——RecyclerView

一、前提

RecyclerView能够灵活实现大数据集的显示,视图的复用管理里ListView更好,能够显示列表,网格,瀑布流等形式,且不同的ViewHolder能够实现item多元化的功能,但是使用起来稍微麻烦一点,并且没有类似的监听事件,需要开发者自己实现

二、目标

RecyclerView

三、内容

1、首先现在buildgrade下添加以下代码,必须添加,否则不能使用RecyclerView

compile 'com.android.support:design:25.3.1'

2、在MainActivity中编写一个RecyclerView组件

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

3、再写一个xml文件用来显示组件,跟ListView一样,在这里只编写一个TextView

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textColor="#000000"
        android:textSize="20sp"
    />

4、MainActivity:
(1)在布局文件中找到RecyclerView
(2)定义一个列表,其中添加数据
(3)向RecyclerView中利用setLayoutManager设置布局管理器
(4)为RecyclerView创建一个适配器

package com.mingrisoft.recyclerview;

import android.graphics.Rect;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Toast;

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

public class LinearRecyclerViewActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_linear_recycler_view);

        //四大组成
        //LayoutManager:Item的布局。
        //Adapter:为Item提供数据。
        //Item Decoration:Item之间的Divider。
        //Item Animator:添加、删除Item动画。

        List<String> data=initData();
        recyclerView= (RecyclerView) findViewById(R.id.rv);

        //RecyclerView提供了三种布局管理器:
        //LinerLayoutManager 以垂直或者水平列表方式展示Item
        //GridLayoutManager 以网格方式展示Item
        //StaggeredGridLayoutManager 以瀑布流方式展示Item

        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        //recyclerView.addItemDecoration(new MyItemDivider(this,R.drawable.style));
        recyclerView.setAdapter(new LinearAdapter(this,data));

    }

    private List<String> initData() {
        List<String> datas=new ArrayList<String>();
        for(int i=0;i<20;i++){
            datas.add("items:"+i);
        }
        return datas;
    }
}

5、新建一个Adapter类继承RecyclerView.Adapter:

(1)Adapter的构造方法,其中输入上下文对象,数据一类的

LayoutInflater 
1.1、首先需要获得其实例,通过.from(context)方法
1.2、其次通过inflate(R.id.xxx,parent,false)方法找到布局文件,并且实例化

(2)创建一个ViewHolder继承与RecyclerView.ViewHolder,其中要添加在布局文件中编写好的组件,创建构造方法,在其中找到组件的位置

(3)onCreateViewHolder方法,为每一个item设置一个view,返回的对象是ViewHolder(layoutinflater.inflate(R.id.xxx,parent,false))

(4)onBindViewHolder适配数据、通过holder.组件.setText(data.get(position))

(5)getItemCount()返回列表的长度data.size()

package com.mingrisoft.recyclerview;

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.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;

/**
 * Created by Administrator on 2020/4/5/005.
 */

public class LinearAdapter extends RecyclerView.Adapter<LinearAdapter.LinearViewHolder> {
    private List<String> datas;
    private Context contexts;
    private LayoutInflater layoutInflater;

    public LinearAdapter(Context context,List<String> data){
        this.datas=data;
        this.contexts=context;
        layoutInflater=layoutInflater.from(contexts);
    }

    class LinearViewHolder extends RecyclerView.ViewHolder{//创建ViewHolder

        private TextView textView;

        public LinearViewHolder(View itemView) {
            super(itemView);
            textView= (TextView) itemView.findViewById(R.id.text);
        }
    }

    @Override
    public LinearAdapter.LinearViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {//为每一个Item inflater出个view

        return new LinearViewHolder(layoutInflater.inflate(R.layout.linear_item,parent,false));
    }

    @Override
    public void onBindViewHolder(LinearAdapter.LinearViewHolder holder, final int position) {//适配数据到view中
        holder.textView.setText(datas.get(position));
    }

    @Override
    public int getItemCount() {//列表的长度
        return datas.size();
    }

}

这样就可以显示页面了

6、绘制分割线

(1)利用背景绘制

首先个MianActivity.xml文件中的RecyclerView添加背景颜色,为黑色

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:background="#000000"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </android.support.v7.widget.RecyclerView>

其次,在另一个xml文件中给布局文件添加背景设为黑色,且外边距设为1dp

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="1dp"
    android:background="#FFFFFF"
    >

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textColor="#000000"
        android:textSize="20sp" />
</RelativeLayout>

效果如图,原因在于,我们先设置大背景为黑色,再设置每个组件的布局文件背景为白色,且相邻组件之间的距离为1dp,这样就可以简便的绘制分割线,但局限性较大,线性布局可以用,但网格布局就很难使用

(2)利用recyclerView.addItemDecoration()方法

此方法非常好用且功能强大

我们需要在MainActivity中添加如下代码,且在res目录下的values/dimens中添加

recyclerView.addItemDecoration(new MyDecoration());

class MyDecoration extends RecyclerView.ItemDecoration{
        @Override
//outRect 用来接收设置的数据,view 是 item 的实例,parent 是 RecyclerView 的实例,state 保存有一些 RecyclerView 的状态
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);//类似实现padding的效果
            //outRect.set()方法设置偏移的大小,其中的参数表示左上右下   
           outRect.set(0,0,0,getResources().getDimensionPixelOffset(R.dimen.divideHeight));
        }
  }

除了outRect.set()方法外,还可以使用outRect.bottom=1;这个方法,其中bottom也可以换成left,right,top

    <dimen name="divideHeight">1dp</dimen>

实现的效果与上图相同

其中getItemOffsets方法实现的功能类似于padding

有兴趣的同学可以查看https://link.jianshu.com/?t=https://github.com/thinkSky1206/android-blog/blob/master/RecyclerView%E4%B9%8BItemDecoration%E7%94%B1%E6%B5%85%E5%85%A5%E6%B7%B1.md

(三)自定义分割线

recyclerView.addItemDecoration(new MyDecoration(this,R.drawable.shape));

class MyDecoration extends RecyclerView.ItemDecoration{
        private Drawable drawable;//drawable是资源文件,自己设定的shape

        public MyDecoration(Context context,int id){
            drawable=context.getResources().getDrawable(id);
        }

        @Override
        public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
            int left=parent.getPaddingLeft();//返回左边距,之所以返回的是边距就是怕左右两边可能会存在滚动条,以免重合
            int right=parent.getWidth()-parent.getPaddingRight();//返回的是宽度-右边距
            int count=parent.getChildCount();//返回一个组中子元素个数的整数

            for(int i=0;i<count;i++){
                View view=parent.getChildAt(i);//item的实例
                int top=view.getBottom();//每个实例的底部
                int bottom=top+drawable.getIntrinsicHeight();
                drawable.setBounds(left, top, right, bottom);
                drawable.draw(c);
            }
        }
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
            outRect.set(0,0,0,drawable.getIntrinsicWidth());
        }
    }

shape.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <gradient
        android:centerColor="#00FF00"
        android:startColor="#FF0000"
        android:endColor="#0000FF"
        android:type="linear"
        />
    <size android:height="1dp" android:width="1dp"/>
</shape>

之前我们介绍过shape属性,这次用到了其中的gradient属性,也就是渐变色

7、格式的互换

在上图中可以看到,每一个itme的内容可以随之更改,这里以后再实际应用中还有更多,这里就拿一个较为简单的案例来实现

首先,再写一个holder和新的xml布局文件,再onCreateViewHolder中我们可以看到有一个int viewType,这个参数是可以通过不同的值展现不同的itemview,通过getItemViewType()方法进行重写,规定指定的位置若为偶数行返回0,奇数行返回1,此时在方法onCreateViewHolder()下进行判断,根据0或1,构建布局文件,结果如上图所示

class LinearViewHolder2 extends RecyclerView.ViewHolder{

        private TextView textView;
        private ImageView imageView;

        public LinearViewHolder2(View itemView) {
            super(itemView);
            textView= (TextView) itemView.findViewById(R.id.tv);
            imageView= (ImageView) itemView.findViewById(R.id.iv);
        }
    }


public int getItemViewType(int position) {//position指的是位置,也就是布局文件中每一行的索引,规定从第0行开始,下面的代码表示偶数行返回0,奇数行返回1
        if(position %2==0){
            return 0;
        }else{
            return 1;
        }
    }


 @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {//可以通过不同的个viewType展现不同的itemView
        if(viewType==0){
            return new LinearViewHolder(layoutInflater.inflate(R.layout.content_main,parent,false));
        }else{
            return new LinearViewHolder2(layoutInflater.inflate(R.layout.content_main2,parent,false));
        }

    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
        if(getItemViewType(position)==0){
            ((LinearViewHolder)holder).textView.setText(datas.get(position));
        }else {
            ((LinearViewHolder2)holder).textView.setText(datas.get(position));
        }
      
    }

8、点击事件

首先在Adapter.java文件下添加一个接口,之后在onBindViewHolder中添加一个事件监听器

private OnItemClickListener mlistener;

public LinearAdapter(Context context,List<String> data,OnItemClickListener listener){
        this.datas=data;
        this.contexts=context;
        layoutInflater=layoutInflater.from(contexts);
        this.mlistener=listener;
    }


public interface OnItemClickListener{//定义一个接口,回调方法为了在MainActivity中直接使用OnClick()方法
        void onClick(int pos);
    }

@Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
        if(getItemViewType(position)==0){
            ((LinearViewHolder)holder).textView.setText(datas.get(position));
        }else {
            ((LinearViewHolder2)holder).textView.setText(datas.get(position));
        }
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Toast.makeText(contexts, "click:" + position, Toast.LENGTH_SHORT).show();
                mlistener.onClick(position);
            }
        });
    }

在MainAvtivity中将setAdapter方法进行修改,这样无论选择哪一个都会显示,不用在每个holder中都定义一个事件监听器

recyclerView.setAdapter(new LinearAdapter(this, data, new LinearAdapter.OnItemClickListener() {
            @Override
            public void onClick(int pos) {
                Toast.makeText(MainActivity.this, "click:"+pos, Toast.LENGTH_SHORT).show();
            }
        }));

以上就是RecyclerView实现列表的操作,至于网格以及瀑布流,其实也很简单,如下代码,只需将setLayoutManger里面的内容进行修改即可

recyclerView.setLayoutManager(new GridLayoutManager(this,3));//3表示列数

//第一个参数根据第二个参数的结构有关,如果是垂直结构vertical则3表示3列,我这里是水平结构,3表示3行
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));

四、总结

RecyclerView的确功能很强大,理清整个逻辑其实并不是很难,需要花点时间去琢磨一下,如果还有其他的问题,今后遇到会做添加。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值