RecyclerView

Android RecyclerView

1.基本介绍:

1.1 什么是RecyclerView

官方的说明:

RecyclerView is a more advanced and flexible version of ListView. This widget is a container for large sets of views that can be recycled and scrolled very efficiently. Use the RecyclerView widget when you have lists with elements that change dynamically.
简单说就是当你需要动态展示一组数据的时候就会需要用到它。
该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、GridView。

1.2 对比listview

用来替代ListView的使用,在RecyclerView标准化了ViewHolder类似于ListView中convertView用来做视图缓存.

先来说说RecyclerView的有点就是,他可以通过设置LayoutManager来快速实现listview、gridview、瀑布流的效果,而且还可以设置横向和纵向显示,添加动画效果也非常简单(自带了ItemAnimation,可以设置加载和移除时的动画,方便做出各种动态浏览的效果),也是官方推荐使用的.
对比listview 的好处。
那么有了ListView、GridView为什么还需要RecyclerView这样的控件呢?整体上看RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。

2 基本使用

2.1 第一个案例

2.1.1 Step1 导包

Step1 导入依赖包 在module的 build.gradle文件中增加recycleview 的依赖包

compile 'com.android.support:recyclerview-v7:23.4.0'

加入后如下

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:recyclerview-v7:23.4.0'
}

2.1.2 Step2声明控件及子view

在mainActivity的layou布局文件中增加recycleview控件

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

-增加recycleview中显示的每个子view的布局
这里写图片描述

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

        android:id="@+id/avatar_image"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="0dp"
            android:layout_weight="1"
            android:paddingLeft="10dp"
            android:layout_height="wrap_content"
            android:id="@+id/rank_text"/>
        <TextView
            android:layout_width="0dp"
            android:layout_weight="2"
            android:gravity="center"
            android:layout_height="wrap_content"
            android:id="@+id/name_text"/>

        <TextView
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/gender_text"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="0dp"
            android:layout_weight="1"
            android:paddingLeft="10dp"
            android:layout_height="wrap_content"
            android:id="@+id/nationality_text"/>

        <TextView
            android:layout_width="0dp"
            android:layout_weight="1"
            android:gravity="center"
            android:layout_height="wrap_content"
            android:id="@+id/work_text"/>
    </LinearLayout>


</LinearLayout>

2.1.3 Step3在MainActivity里写代码

Step3:在MainActivity里写代码

1.准备数据recycleview里放的数据

声明成员变量

private List<Star> stars;

一个javaBean

package com.example.recyclerview.bean;

/**
 * Created by CryRobot.
 *  rank,姓名,国籍 及 照片性别,作品
 */

public class Star {
    private int rank;
    private String name;
    private String nationality;
    private int avatar;
    private String gender;
    private String works;

    public int getRank() {
        return rank;
    }

    public void setRank(int rank) {
        this.rank = rank;
    }

    public String getName() {
        return name;
    }

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

    public String getNationality() {
        return nationality;
    }

    public void setNationality(String nationality) {
        this.nationality = nationality;
    }

    public int getAvatar() {
        return avatar;
    }

    public void setAvatar(int avatar) {
        this.avatar = avatar;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getWorks() {
        return works;
    }

    public void setWorks(String works) {
        this.works = works;
    }

    @Override
    public String toString() {
        return "Star{" +
                "rank=" + rank +
                ", name='" + name + '\'' +
                ", nationality='" + nationality + '\'' +
                ", avatar='" + avatar + '\'' +
                ", gender='" + gender + '\'' +
                ", works='" + works + '\'' +
                '}';
    }

    public Star(int rank, String name, String nationality, int avatar, String gender, String works) {
        this.rank = rank;
        this.name = name;
        this.nationality = nationality;
        this.avatar = avatar;
        this.gender = gender;
        this.works = works;
    }


    public Star() {
    }
}

写一个initData初始化之

private void initData() {
        stars = new ArrayList<Star>();
        Star star1 = new Star(11,"周杰伦","中国",R.drawable.zhoujielun,"男","稻香");
        Star star2 = new Star(12,"施瓦辛格","美国",R.drawable.shiwaxinge,"男","终结者");
        Star star3 = new Star(13,"黛安娜","英国",R.drawable.daianna,"女","开罗紫玫瑰");
        Star star4 = new Star(14,"李小龙","中国",R.drawable.lixiaolong,"男","精武门");
        Star star5 = new Star(15,"史泰龙","中国",R.drawable.sitailong,"男","洛奇");
        stars.add(star1);
        stars.add(star2);
        stars.add(star3);
        stars.add(star4);
        stars.add(star5);

    }

在oncreate里调用initData (); 可以完成数据的初始化

2.实现recycleview的适配器:
适配器实现如下:

class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder>{


        //创建保持view控件的holder
        @Override
        public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            //将
            MyHolder myHolder = new MyHolder(View.inflate(MainActivity.this,R.layout.list_item,null));
            return myHolder;
        }

        //设置每个view的显示内容
        @Override
        public void onBindViewHolder(MyHolder holder, int position) {
            Star star = stars.get(position);

            int rank = star.getRank();
            String name = star.getName();
            String nationality = star.getNationality();
            int avatar = star.getAvatar();
            String gender = star.getGender();
            String works = star.getWorks();
            ViewGroup.LayoutParams layoutParams = holder.avatar_image.getLayoutParams();
            if(position%2==0){

                layoutParams.height = 550;
            }else{
                layoutParams.height = 600;
            }

            holder.rank_text.setText(rank+"");
            holder.avatar_image.setImageResource(avatar);
            holder.name_text.setText(name);
            holder.nationality_text.setText(nationality);
            holder.gender_text.setText(gender);
            holder.work_text.setText(works);


        }

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

        //控件存放。findiew
        class MyHolder extends RecyclerView.ViewHolder{

            TextView rank_text ;
            TextView name_text ;
            TextView nationality_text;
            TextView gender_text ;
            TextView work_text ;
            ImageView avatar_image;
            LinearLayout itemLayout;
            public MyHolder(View itemView) {
                super(itemView);
                rank_text = (TextView)itemView.findViewById(R.id.rank_text);
                name_text = (TextView)itemView.findViewById(R.id.name_text);
                nationality_text = (TextView)itemView.findViewById(R.id.nationality_text);
                gender_text = (TextView)itemView.findViewById(R.id.gender_text);
                work_text = (TextView)itemView.findViewById(R.id.work_text);
                avatar_image = (ImageView)itemView.findViewById(R.id.avatar_image);
                itemLayout = (LinearLayout) itemView.findViewById(R.id.itemLayout);

            }
        }

    }

3.在oncreate里去设置recycleview的使用。

以上完成后,可以看到效果如下;

这样recycleview的初步使用就搞定了!

2.2 第一个案例解释

上面案例我们使用到了一个新的Adapter,它里面有一个内部类和几个callback,我们来解释一下。
首先看下Adapter里的内部类

从命名就可以看到,这是一个viewholder的具体实现。
这跟我们之前讲的viewholder实现一样,就是用这个类去保存一个控件,我们复用的时候直接从这个holder里拿出来即可。

接下来看adapter里的几个callback函数
onCreateViewHolder
在listview里,我们比较熟悉viewholder的概念。就是为了复用view而在recycleview里onCreateViewHolder就是为了复用view。
所以就不用自己去创建viewholder了,在需要创建viewholder的时候,这个api会自动调用,去创建viewholder。
onBinderViewHolder(holder,position)

类似于listview里的getView(position),给你一个position,并给你一个可以复用的holder,那你只需要填充数据就行. 这里我们就根据传入的position到我们的数据集合里去找对应的position要显示什么数据,然后设置到这个viewholder里对应的view上即可。
getItemCount()
这个api类似之前的getCount()就是获取我这个recycleview里一共要显示多少个数据.


3 进阶使用

好了,上面通过使用其默认的LinearLayoutManager。

实现了类似ListView样子的Demo。

给recycleview设置LayoutManager这是一个抽象类,好在系统提供了3个实现类:
LinearLayoutManager 现行管理器,支持横向、纵向。
GridLayoutManager 网格布局管理器
StaggeredGridLayoutManager 瀑布就式布局管理器

上面我们已经初步体验了下LinearLayoutManager,
接下来看GridLayoutManager。

3.1更改样式

3.1.1GridLayoutManager

要更改LayoutManager为GridLayoutManager,只需要做如下修改即可

其中GridLayoutManager第二个参数的意思是:
The number of columns in the grid
即这个网格布局每一行有几列。

更换之后我们可以看到布局变成了这样。

每行变成了四列。这其实就是一个GridView。

3.1.2StaggeredGridLayoutManager

Staggered 意为 错列的,错开的;

要更改LayoutManager为StaggeredGridLayoutManager,只需要做如下修改即可

其中StaggeredGridLayoutManager
构造函数的两个参数的意义分别为:
第二个参数是当前的recycleview是水平延伸还是竖直延伸。
第一个参数spancount :
如果是水平方向延伸,它表示几行数据
如果是竖直方向延伸,表示由几列数据。

我们以竖直方向延伸,spancount=3为例,效果如下,可以在竖直方向拖动

而若以水平方向延伸,spancount=3为例,效果如下,可以在水平方向拖动

3.2 增加控件之间的间隔

RecycleView提供了如下的API让我们去设置item之间的间隔。
mRecyclerView.addItemDecoration(decoration);

这里需要传入一个ItemDecoration,这是个抽象类

       recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
            @Override
            public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
                super.getItemOffsets(outRect, view, parent, state);
                outRect.bottom = 8;
                outRect.top = 8;
                outRect.right=18;
                outRect.left=18;

            }
        });

官方目前并没有提供默认的实现类(囧)。
自己去实现。
该类并没有抽象方法,我们要自己去重写它的getItemOffsets方法

这个方法的作用是让我们去设定每一个item上下左右的留白。
我们做如上面所示:
outRect为item的四周矩形
通过构造函数传入一个留白像素值,那么上下左右我们都留这么大距离

写完之后,可以给recycleView设置我们自己实现的ItemDecoration

效果如下:(设置前面的对比)
设置前(图片取的不好,勿怪)
这里写图片描述

设置后:
这里写图片描述

3.3 瀑布流效果的实现

3.3.1 什么是瀑布流效果?

3.3.2 如何实现?

思路分析
从之前的介绍可以发现,瀑布流效果实际上是StaggeredGridLayoutManager,然后每个填充的view高度不同即可。
根据上述思路,我们来实现。

        StaggeredGridLayoutManager staggeredLay = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(staggeredLay);

先回顾下之前我们的Adapter里面,返回的view是怎么做的

现在需要返回控件高度不一样。因为目前我们是三列,竖直方向。我们可以做如下修改,增加红色框内代码,动态调整每个子view的高度:

ViewGroup.LayoutParams layoutParams = holder.avatar_image.getLayoutParams();
            if(position%2==0){

                layoutParams.height = 550;
            }else{
                layoutParams.height = 600;
            }

完成之后效果如下:

这里写图片描述

上下拖动可以看到瀑布流效果已经实现


4更多

未完,待续。


[完整代码:]

package com.example.recyclerview;

import android.graphics.Rect;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.example.recyclerview.bean.Star;

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

public class MainActivity extends AppCompatActivity {


    private List<Star> stars;
    private RecyclerView recyclerView;

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

        recyclerView = (RecyclerView) findViewById(R.id.rv);

        //1.初始化数据
        initDate();
        //2.实现recycleview的适配器:
       // recyclerView.setLayoutManager(new LinearLayoutManager(this));
       // recyclerView.setLayoutManager(new GridLayoutManager(this,3));
        StaggeredGridLayoutManager staggeredLay = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(staggeredLay);
        MyAdapter myAdapter = new MyAdapter();

        recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
            @Override
            public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
                super.getItemOffsets(outRect, view, parent, state);
                outRect.bottom = 8;
                outRect.top = 8;
                outRect.right=18;
                outRect.left=18;

            }
        });


        recyclerView.setAdapter(myAdapter);

 /*       //这里不能为每个item设置点击事件
        recyclerView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Intent intent = new Intent();

            }
        });*/


    }

    private void initDate() {
        stars = new ArrayList<Star>();
        Star star1 = new Star(11,"周杰伦","中国",R.drawable.zhoujielun,"男","稻香");
        Star star2 = new Star(12,"施瓦辛格","美国",R.drawable.shiwaxinge,"男","终结者");
        Star star3 = new Star(13,"黛安娜","英国",R.drawable.daianna,"女","开罗紫玫瑰");
        Star star4 = new Star(14,"李小龙","中国",R.drawable.lixiaolong,"男","精武门");
        Star star5 = new Star(15,"史泰龙","中国",R.drawable.sitailong,"男","洛奇");
        stars.add(star1);
        stars.add(star2);
        stars.add(star3);
        stars.add(star4);
        stars.add(star5);

    }

    class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder>{


        //创建保持view控件的holder
        @Override
        public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            //将
            MyHolder myHolder = new MyHolder(View.inflate(MainActivity.this,R.layout.list_item,null));
            return myHolder;
        }

        //设置每个view的显示内容
        @Override
        public void onBindViewHolder(MyHolder holder, int position) {
            Star star = stars.get(position);

            int rank = star.getRank();
            String name = star.getName();
            String nationality = star.getNationality();
            int avatar = star.getAvatar();
            String gender = star.getGender();
            String works = star.getWorks();
            ViewGroup.LayoutParams layoutParams = holder.avatar_image.getLayoutParams();
            if(position%2==0){

                layoutParams.height = 550;
            }else{
                layoutParams.height = 600;
            }

            holder.rank_text.setText(rank+"");
            holder.avatar_image.setImageResource(avatar);
            holder.name_text.setText(name);
            holder.nationality_text.setText(nationality);
            holder.gender_text.setText(gender);
            holder.work_text.setText(works);


        }

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

        //控件存放。findiew
        class MyHolder extends RecyclerView.ViewHolder{

            TextView rank_text ;
            TextView name_text ;
            TextView nationality_text;
            TextView gender_text ;
            TextView work_text ;
            ImageView avatar_image;
            LinearLayout itemLayout;
            public MyHolder(View itemView) {
                super(itemView);
                rank_text = (TextView)itemView.findViewById(R.id.rank_text);
                name_text = (TextView)itemView.findViewById(R.id.name_text);
                nationality_text = (TextView)itemView.findViewById(R.id.nationality_text);
                gender_text = (TextView)itemView.findViewById(R.id.gender_text);
                work_text = (TextView)itemView.findViewById(R.id.work_text);
                avatar_image = (ImageView)itemView.findViewById(R.id.avatar_image);
                itemLayout = (LinearLayout) itemView.findViewById(R.id.itemLayout);

            }
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值