目录
1.例子1:线性RecycleView的简单使用(类似ListVIew)
附加1:增加图片
附加2:增加分割线
2.例子2:为RecyclerView设置点击事件监听
3.例子3:线性水平RecycleView的简单使用
4.例子4:网格视图的RecyclerView的简单使用(类似GridView)
附加1:为网格视图增加监听器
5.例子5:RecyclerView实现瀑布流布局
6.RecyclerView根据不同的ViewHolder实现不同的Item
Demo地址:https://github.com/zGuangYuan/Androidstudio_example
前言:RecycleView能够灵活实现大数据的展示,视图的复用管理比ListView更好,能够显示列表、网格、瀑布流等形式、且不同的ViewHolder能够实现item多元化的功能。
先演示效果,如下:
注意:使用RecyceView需要添加一个RecycleView的依赖包:
compile 'com.android.support:recyclerview-v7:25.3.1'
导入哪个版本的依赖包,主要是看你是哪一个版本的RecycleView
在:你的SDK安装位置\extras\android\m2repository\com\android\support 文件夹下,就是依赖包
可以选择一个版本的依赖包,但是最好和你的 targetSdkVersion 是同版本的,否则会有警告
我在这里导入了一个 25.3.1版本的,因为我的targetSdkVersion 是28所以会警告,但是不影响使用
点击如下图标,导入依赖包,如果没有报错就是导入成功了:
新建应用程序后,新建一个包RecycleView:
在这个包中新建一个Activity,命名为:RecycleViewActivity
在布局文件新建一个Button控件:
然后再RecycleViewActivity,绑定按钮的监听器(LinearRecycleViewActivity下面创建):
注意new Intent之后,还需要去启动这个Intent对象。startActivity(intent);
新建一个列表视图的Empty Activity,命名为:LinearRecycleViewActivity:
接下俩修改Manifest.xml文件,把默认的Activity设为 RecycleViewActivity
现在视图就是这样子:
点击上面的列表视图,进入 LinearRecycleViewActivity这个Activity:
新建一个Adapter,继承自RecycleView的Adapter:
复写父类的方法:
看一下Adapter的原型函数:
可以看到Adapter有一个指定的泛型,这个泛型是继承自ViewHolder的,那我们就需要去创建这个泛型,然后传进去:
在里面新建一个LInearVIewHolder继承ViewHolder:然后创建它的构造方法:
生成一个构造函数:
然后把这个泛型,传进去给Adapter,然后修改复写函数的返回值,和传入参数类型:
接下来新建一个布局文件,用于在RecycleView显示的图片和文字之类的控件,命名为:layout_linearrv_item,根布局为:Linearlayout
然后画一个简单的TextView控件就可以了:
现在主要是LinearAdapter.java这个类(继承自RecycleView的Adapter):
声明引用,创建一个构造函数引入Contex类型的变量,目的是引入加载需要用到的布局文件
在ViewHolder的子类的构造函数中,获取布局文件的控件对象:
复写onCreateViewHolder,在此方法中,调用LinearViewHolder,其构造函数传进去一个View类型的参数,把传进来的布局文件作为参数传进去,这样onCreateViewHolder函数就复写完成了:
可以在onBindViewHolder方法中,去修改传进来布局文件的属性,修改为:Hello Yuan!
整体代码:
package com.example.yuan.e06_gridview.RecycleView;
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.TextView;
import com.example.yuan.e05_listview.R;
public class LinearAdapter extends RecyclerView.Adapter {
//声明引用
private Context mContext;
private LayoutInflater mLayoutInflater;
//创建一个构造函数
public LinearAdapter(Context context){
this.mContext=context;
//利用LayoutInflater把控件所在的布局文件加载到当前类当中
mLayoutInflater = LayoutInflater.from(context);
}
//此方法要返回一个ViewHolder
@Override
public LinearAdapter.LinearViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new LinearViewHolder(mLayoutInflater.inflate(R.layout.layout_linearrv_item,parent,false));
}
//通过holder设置TextView的内容
@Override
public void onBindViewHolder(LinearAdapter.LinearViewHolder holder, int position) {
holder.textView.setText("Hello Yuan!");
}
@Override
public int getItemCount() {
return 25;
}
class LinearViewHolder extends RecyclerView.ViewHolder{
//声明layout_linearrv_item布局控件的变量
private TextView textView;
public LinearViewHolder(View itemView) {
super(itemView);
textView =(TextView) itemView.findViewById(R.id.TV_RVLinear_title_Id);
}
}
}
已上编写完成之后基本完成,现在返回到LinearRecycleViewActivity.java中去生成这个RecycleView的Adapter的对象,然后把RecycleView所在的Activity传进去就OK了。
回到LinearRecycleViewActivity,修改如下:
运行应用程序:
点击按钮后如下显示,总共是25个条目,且背景为橙色,可以上下滑动看完全部条目:
可以让这些条目显示的多元化一点吗,当然可以,只需要在这基础上做一些简单的修改即可,比如,再让这个线性的RecycleView再加载一张网络图片,如何做?
首先修改下面layout_linearrv_item.xml这个布局文件,增加一个ImageView控件:
然后只需回到,LinearAdapter.java中作出一些简单的修改,去获取ImageView控件对象,然后修改控件的性就行了:
第三方图片来源于网络,地址从下图赋值出来:
提示:如何加载第三方网络图片:点我查看
运行应用程序,如下图所示,总共有25个条目,可以向下滑动:
可以看见两个条目之间是没有分割线的,但是我们可以去自定义分割线,然后应用到这个线性的RecyclerView上:
使用addItemDecoration()方法可以用来设置分割线,传进去的参数是ItemDecotation类型的对象:
ItemDecotation是个抽象类
里面有三个有效的方法:
方法一:
方法2:
方法三:
那我们使用方法三,因为他是抽象类,抽象类不能生成对象,所以我们去继承它,然后复写它的抽象方法:
整体代码:
package com.example.yuan.e06_gridview.RecycleView;
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 com.example.yuan.e05_listview.R;
public class LinearRecycleViewActivity extends AppCompatActivity {
private RecyclerView mRVMain;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_linear_recycle_view);
mRVMain=(RecyclerView) findViewById(R.id.RV_main_Id);
//设置线性布局管理器
mRVMain.setLayoutManager(new LinearLayoutManager(LinearRecycleViewActivity.this));
//Item装饰
mRVMain.addItemDecoration(new MyDecoration());
//设置Adapter
mRVMain.setAdapter(new LinearAdapter(LinearRecycleViewActivity.this, new LinearAdapter.OnItemClickListener() {
@Override
public void OnClick(int position) {
Toast.makeText(LinearRecycleViewActivity.this,"点击位置"+position,Toast.LENGTH_SHORT).show();
}
}));
//继承ItemDecoration类
}
class MyDecoration extends RecyclerView.ItemDecoration{
//复写getItemOffsets方法
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.set(0,0,0,getResources().getDimensionPixelOffset(R.dimen.dividerHeight));
}
}
}
新建一个resource文件命名为:decoration:
设置分割线属性:
注意:因为分割线是RecycleView的背景色(灰色),为了看的更清楚改一下, layout_linearav_ietm.xml布局文件中TextView控件的背景色。如下:
运行应用程序,就可以看到这个分割线了 ,每一个条目下面都有一个3dp的分割线:
方式一:直接在LinearAdapter的onBindViewHolder()方法中直接实现监听器接口,然后绑定监听器即可:
运行应用程序,点击列表视图:
点击条目,显示点击位置:
方式二:因为RecyclerView没有和ListView和GridView一样在外部有监听器接口,但是可以通过回调函数在外部实现监听的方法(不同类),想在LinearRecycleView.java中实现监听怎么做?
原理:在LinearAdapter这个类里面写一个接口,然后在LinearRecycleView实现这个接口,然后复写里面的Onclick()方法,通过函数的回调实现在LinearRecycleView这个类监听LinearAdapter这个类的事件:
1.在LinearAdapter定义一个接口
接收来自外部的实现类对象:
数据回调:
整体代码:
package com.example.yuan.e06_gridview.RecycleView;
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.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.example.yuan.e05_listview.R;
public class LinearAdapter extends RecyclerView.Adapter {
//声明引用
private Context mContext;
private LayoutInflater mLayoutInflater;
private OnItemClickListener mlistener;
//创建一个构造函数
public LinearAdapter(Context context,OnItemClickListener listener){
this.mContext=context;
//利用LayoutInflater把控件所在的布局文件加载到当前类当中
mLayoutInflater = LayoutInflater.from(context);
//从外部传进来一个OnItemClickListener子类的变量
this.mlistener=listener;
}
//此方法要返回一个ViewHolder
@Override
public LinearAdapter.LinearViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new LinearViewHolder(mLayoutInflater.inflate(R.layout.layout_linearrv_item,parent,false));
}
//通过holder设置TextView的内容
@Override
public void onBindViewHolder(LinearAdapter.LinearViewHolder holder, final int position) {
holder.textView.setText("模特");
Glide.with(mContext).load("http://img.zcool.cn/community/01c8b4557aca590000002d5c60d85e.jpg@1280w_1l_2o_100sh.jpg").into(holder.imageView);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mlistener.OnClick(position);
//点击后弹窗,显示点击位置
//Toast.makeText(mContext,"点击位置"+position,Toast.LENGTH_SHORT).show();
}
});
}
@Override
public int getItemCount() {
return 25;
}
class LinearViewHolder extends RecyclerView.ViewHolder{
//声明layout_linearrv_item布局控件的变量
private TextView textView;
private ImageView imageView;
public LinearViewHolder(View itemView) {
super(itemView);
textView =(TextView) itemView.findViewById(R.id.TV_RVLinear_title_Id);
imageView=(ImageView) itemView.findViewById(R.id.IVLinear_picture_Id);
}
}
//定义一个接口
public interface OnItemClickListener{
//接口默认都是抽象的方法,且类型都是public
void OnClick(int position);
}
}
2.在LinearRecycleView.java中,
运行应用程序,执行的结果和方式一一样,方式二采用了回调的方法:
注意:那么设置长点击事件也是一样的,调用holder.itemView.setOnLongClickListener();复写里面的方法,想要在外部调用就采用回调的方法。
先演示效果,如下:
新建一个Empty Activity,命名为:HorLinearRecyclerViewActivity
在activity_recycle_view.xml这个布局文件,增加一个按钮跳转到HorLinearRecyclerViewActivity这个Activity:
为按钮绑定监听器:
整体代码:
package com.example.yuan.e06_gridview.RecycleView;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.example.yuan.e05_listview.R;
public class RecycleViewActivity extends AppCompatActivity {
//声明引用
private Button mLinearButton;
private Button mHorLinearButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycle_view);
//获取控件对象
mLinearButton=(Button) findViewById(R.id.button_linearRV_Id);
mHorLinearButton=(Button) findViewById(R.id.button_linearRV2_Id);
setlistener();
}
public void setlistener(){
//生成监听器对象
ButtonListener listener = new ButtonListener();
//绑定监听器
mLinearButton.setOnClickListener(listener);
mHorLinearButton.setOnClickListener(listener);
}
class ButtonListener implements OnClickListener{
@Override
public void onClick(View v) {
Intent intent =null;
switch(v.getId()){
case R.id.button_linearRV_Id:
intent = new Intent(RecycleViewActivity.this,LinearRecycleViewActivity.class);
break;
case R.id.button_linearRV2_Id:
intent = new Intent(RecycleViewActivity.this,HorLinearRecyclerViewActivity.class);
}
startActivity(intent);
}
}
}
在水平滚动这个Activity的布局文件增加加一个 RecylcerView控件:
然后再HorLinearRecyclerViewActivity的Activity中新建一个线性布局管理器,把布局改成水平方向,并为RecyclerView对象设置一个适配器:
还没有为这个RecyclerView对象设置适配器,下面为它设置一个Adapter.
整体代码:
package com.example.yuan.e06_gridview.RecycleView;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Button;
import android.widget.Toast;
import com.example.yuan.e05_listview.R;
public class HorLinearRecyclerViewActivity extends AppCompatActivity {
private RecyclerView mhorRV;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hor_linear_recycler_view);
mhorRV=(RecyclerView) findViewById(R.id.RV_hor_Id);
//设置一个线性布局管理器,因为要设置方向,就不采用匿名内部类的方式了
//生成一个LinearLayoutManager的对象
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(HorLinearRecyclerViewActivity.this);
//设置这个线性布局管理器的方向,为水平方向
linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
//设置mHorRV的线性布局管理器
mhorRV.setLayoutManager(linearLayoutManager);
//设置适配器:Adapter
mhorRV.setAdapter(new HorLinearAdapter(HorLinearRecyclerViewActivity.this));
}
}
设置适配器:
由于和前面的LinearAdapter的内容基本类似,故直接复制一份就行了,只要在那基础上稍作修改就OK了:
操作:
弹出窗口,改个名字:HorLinearAdapter,
然后还需要item的布局文件,同样赋值一份,稍作修改就可以(其实直接用同一份也是可以的),为了规范化,再复制一份:
复制下面这份item布局文件:
复制后重命名:layout_horlinearrv_item.xml
修改下内容,把控件的Id也修改了:
整体代码如下:
回到HorLinearAdapter的布局修改成上面的那个布局文件
整体代码如下:
package com.example.yuan.e06_gridview.RecycleView;
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.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.example.yuan.e05_listview.R;
public class HorLinearAdapter extends RecyclerView.Adapter {
//声明引用
private Context mContext;
private LayoutInflater mLayoutInflater;
//创建一个构造函数
public HorLinearAdapter(Context context){
this.mContext=context;
//利用LayoutInflater把控件所在的布局文件加载到当前类当中
mLayoutInflater = LayoutInflater.from(context);
}
//此方法要返回一个ViewHolder
@Override
public HorLinearAdapter.LinearViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new LinearViewHolder(mLayoutInflater.inflate(R.layout.layout_horlinearrv_item,parent,false));
}
//通过holder设置TextView的内容
@Override
public void onBindViewHolder(HorLinearAdapter.LinearViewHolder holder, final int position) {
holder.textView.setText("模特");
Glide.with(mContext).load("http://img.zcool.cn/community/01c8b4557aca590000002d5c60d85e.jpg@1280w_1l_2o_100sh.jpg").into(holder.imageView);
}
@Override
public int getItemCount() {
return 10;
}
class LinearViewHolder extends RecyclerView.ViewHolder{
//声明layout_linearrv_item布局控件的变量
private TextView textView;
private ImageView imageView;
public LinearViewHolder(View itemView) {
super(itemView);
textView =(TextView) itemView.findViewById(R.id.TV_RVhorLinear_title_Id);
imageView=(ImageView) itemView.findViewById(R.id.IVhorLinear_picture_Id);
}
}
}
运行应用程序,如下:
点击水平滚动视图,进入下面这个界面,可以左右滑动:
水平视图同样可以设置分割线和点击监听事件,和上面一样的方法。不赘述 。
先演示效果,如下:
新建一个Empty Activity,命名为:GridRecyclerViewActivity.
然后在activity_recyle_view.xml,文件添加一个按钮控件:
在RecyclerViewActivity.java中为这个按钮绑定监听器,跳转到网格视图这个Activity(GridRecyclerViewActivity)
整体代码如下:
package com.example.yuan.e06_gridview.RecycleView;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.example.yuan.e05_listview.R;
import com.example.yuan.e06_gridview.GridView.GridViewActivity;
public class RecycleViewActivity extends AppCompatActivity {
//声明引用
private Button mLinearButton;
private Button mHorLinearButton;
private Button mGridButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycle_view);
//获取控件对象
mLinearButton=(Button) findViewById(R.id.button_linearRV_Id);
mHorLinearButton=(Button) findViewById(R.id.button_linearRV2_Id);
mGridButton=(Button) findViewById(R.id.button_gridRV3_Id);
setlistener();
}
public void setlistener(){
//生成监听器对象
ButtonListener listener = new ButtonListener();
//绑定监听器
mLinearButton.setOnClickListener(listener);
mHorLinearButton.setOnClickListener(listener);
mGridButton.setOnClickListener(listener);
}
class ButtonListener implements OnClickListener{
@Override
public void onClick(View v) {
Intent intent =null;
switch(v.getId()){
case R.id.button_linearRV_Id:
intent = new Intent(RecycleViewActivity.this,LinearRecycleViewActivity.class);
break;
case R.id.button_linearRV2_Id:
intent = new Intent(RecycleViewActivity.this,HorLinearRecyclerViewActivity.class);
case R.id.button_gridRV3_Id:
intent = new Intent(RecycleViewActivity.this, GridRecyclerViewActivity.class);
}
startActivity(intent);
}
}
}
回到activity_grid_recycler_view.xml这个布局文件,增加一个RecyclerView控件(设置了橙色背景):
回到对应的Activity(GridRecyclerView.java)声明一下上面的RecyclerView控件,设置布局管理器,设置适配器:
接下来就设置一个新建一个类,继承自RecyclerView的Adapter,然后复写它的方法,去写一个适配器,具体过程在第一个例子
已经详细展示,故不做多解释:
1.新建一个类,命名为:GridRecyclerViewAdapter,继承自RecyclerView的Adapter
2.复写Adapter的抽象方法:
3.查看Adapter的函数原型,有指定一个泛型,参数是ViewHolder的子类:
4.创建一个类继承ViewHolder,命名为MyViewHolder,并创建一个构造函数:
5.然后把指定泛型修改一下,总共三处:
6. 新增加一个item的布局文件,为这个网格的RecyclerView提供空间的来源:
6.1新建一个布局文件,命名为:layout_grid_recyclerview_item.xml,根布局为线性布局:
6.2在这个Gird上,显示一张图片和一行文字,需要ImageView控件和TextView控件:
7.在GridRecyclerView.java的类中,新建一个构造函数,接受来自调用的Context,有两个作用,第一:用于第三方网络图片加加载,第二:用于把 layout_grid_recyclerview_item布局文件引入到当前类当中:
8.复写第一个方法,把layout_grid_recyclerview_item布局文件加载到当前类当中:
这样的话MyViewHolder类就可以使用 layout_grid_recyclerview_item布局文件的控件了:
9.写MyViewHolder构造函数的东西:
10.为网格视图设置文字和图片属性:
现在这个Adapter的内容都编写完了:整体代码:
package com.example.yuan.e06_gridview.RecycleView;
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.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.example.yuan.e05_listview.R;
public class GridRecyclerViewAdapter extends RecyclerView.Adapter {
//声明引用
private Context mContext;
private LayoutInflater mLayoutInflater;
//创建一个构造函数:
public GridRecyclerViewAdapter(Context context){
this.mContext=context;
//利用LayoutInflater把控件所在的布局文件加载到当前类当中
mLayoutInflater = LayoutInflater.from(context);
}
@Override
public GridRecyclerViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//返回一个ViewHolder类型的数据,返回ViewHolder子类的对象,把布局文件加载到当前类返回
return new MyViewHolder(mLayoutInflater.inflate(R.layout.layout_grid_recyclerview_item,parent,false));
}
@Override
public void onBindViewHolder(GridRecyclerViewAdapter.MyViewHolder holder, int position) {
holder.textView.setText("跑车");
Glide.with(mContext).load("http://image.bitautoimg.com/appimage/media/20170317/w1600_h900_f6a5cad43dda443184bc2a6d5ecf44b4.jpeg").into(holder.imageView);
}
@Override
public int getItemCount() {
return 10;
}
public class MyViewHolder extends RecyclerView.ViewHolder{
//声明引用
private ImageView imageView;
private TextView textView;
public MyViewHolder(View itemView) {
super(itemView);
//获取控件对象
imageView=(ImageView) itemView.findViewById(R.id.IV_GridRV_Id);
textView=(TextView) itemView.findViewById(R.id.TV_GridRV_Id);
}
}
}
11.回到GridRecyclerView.java,生成适配器对象,调用适配器:
已上一个网格视图的基本设置已经完成。
运行这个应用程序,点击网格视图:
总共十个条目,且RecyclerView的背景色为橙色,图片宽度150*150dp。
只需在onBindViewHolde()方法中设置,监听器即可,以弹窗的方式显示出来:
运行应用程序,这样就可以监听啦,然后根据需要自己扩展:
这个同样可以设置按压效果,分割线等等的功能,在上面的例子已经展示的很清楚了。
先演示效果,如下:
老样子,还是用实例来演示如何使用:
1.新建一个Empty Activity,命名为:WaterfallRecyclerViewActivity
2,然后在activity_recyle_view.xml,文件添加一个按钮控件,并绑定监听器:
绑定监听器,代码如下:
package com.example.yuan.e06_gridview.RecycleView;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.example.yuan.e05_listview.R;
import com.example.yuan.e06_gridview.GridView.GridViewActivity;
public class RecycleViewActivity extends AppCompatActivity {
//声明引用
private Button mLinearButton;
private Button mHorLinearButton;
private Button mGridButton;
private Button mWaterfallButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycle_view);
//获取控件对象
mLinearButton=(Button) findViewById(R.id.button_linearRV_Id);
mHorLinearButton=(Button) findViewById(R.id.button_linearRV2_Id);
mGridButton=(Button) findViewById(R.id.button_gridRV3_Id);
mWaterfallButton=(Button) findViewById(R.id.button_waterfallRV4_Id);
setlistener();
}
public void setlistener(){
//生成监听器对象
ButtonListener listener = new ButtonListener();
//绑定监听器
mLinearButton.setOnClickListener(listener);
mHorLinearButton.setOnClickListener(listener);
mGridButton.setOnClickListener(listener);
mWaterfallButton.setOnClickListener(listener);
}
class ButtonListener implements OnClickListener{
@Override
public void onClick(View v) {
Intent intent =null;
switch(v.getId()){
case R.id.button_linearRV_Id:
intent = new Intent(RecycleViewActivity.this,LinearRecycleViewActivity.class);
break;
case R.id.button_linearRV2_Id:
intent = new Intent(RecycleViewActivity.this,HorLinearRecyclerViewActivity.class);
break;
case R.id.button_gridRV3_Id:
intent = new Intent(RecycleViewActivity.this, GridRecyclerViewActivity.class);
break;
case R.id.button_waterfallRV4_Id:
intent=new Intent(RecycleViewActivity.this,WaterfallRecyclerViewActivity.class);
}
startActivity(intent);
}
}
}
回到activity_waterfall_recycler_view.xml这个布局文件,增加一个RecyclerView控件(设置了橙色背景):
回到对应的Activity(WaterfallRecyclerView.java)声明一下上面的RecyclerView控件,设置布局管理器,设置适配器:
接下来就设置一个新建一个类,继承自RecyclerView的Adapter,然后复写它的方法,去写一个适配器:
新建一个类,命名为:WaterfallRecyclerViewAdapter
前面的例子步骤已经很详细了,故这部分直接给代码,不做解释:
package com.example.yuan.e06_gridview.RecycleView;
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.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.example.yuan.e05_listview.R;
public class WaterfallRecyclerViewAdapter extends RecyclerView.Adapter {
//声明引用
private Context mContext;
private LayoutInflater mLayoutInflater;
//创建一个构造函数:
public WaterfallRecyclerViewAdapter(Context context){
this.mContext=context;
//利用LayoutInflater把控件所在的布局文件加载到当前类当中
mLayoutInflater = LayoutInflater.from(context);
}
@Override
public WaterfallRecyclerViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//返回一个ViewHolder类型的数据,返回ViewHolder子类的对象,把布局文件加载到当前类返回
return new MyViewHolder(mLayoutInflater.inflate(R.layout.layout_waterfall_recyclerview_item,parent,false));
}
@Override
public void onBindViewHolder(WaterfallRecyclerViewAdapter.MyViewHolder holder, final int position) {
if(position % 2 ==0){
holder.imageView.setImageResource(R.drawable.flower);
}else{
holder.imageView.setImageResource(R.drawable.girls);
}
//设置监听器,短点击
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext,"短点击位置"+position,Toast.LENGTH_SHORT).show();
}
});
//长点击
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
Toast.makeText(mContext,"长点击位置"+position,Toast.LENGTH_SHORT).show();
return false;
}
});
}
@Override
public int getItemCount() {
return 30;
}
public class MyViewHolder extends RecyclerView.ViewHolder{
//声明引用
private ImageView imageView;
public MyViewHolder(View itemView) {
super(itemView);
//获取控件对象
imageView=(ImageView) itemView.findViewById(R.id.IV_waterfallRV_Id);
}
}
}
新增加一个item的布局文件,为这个网格的RecyclerView提供空间的来源:
1.新建一个布局文件,命名为:layout_waterfall_recyclerview_item.xml
因为是显示瀑布流形式,所以只放两张大小不一样的图片,所以需要两个ImageView控件:
需要两张大小不一样的图片,直接从网上下本地,然后放到drawable文件夹下,待会引用就行了:
在最后一步设置一个Adapter就行了:
整体代码:
package com.example.yuan.e06_gridview.RecycleView;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import com.example.yuan.e05_listview.R;
public class WaterfallRecyclerViewActivity extends AppCompatActivity {
//声明引用
private RecyclerView mWaterfallRV;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_waterfall_recycler_view);
//获取控件对象
mWaterfallRV=findViewById(R.id.RV_waterfall_Id);
//设置布局管理器,两个参数,如果后面参数是垂直就代表第一个是几列,如果是水平,第一个就代表行数
mWaterfallRV.setLayoutManager(new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL));
//设置Adapter
mWaterfallRV.setAdapter(new WaterfallRecyclerViewAdapter(WaterfallRecyclerViewActivity.this));
}
}
运行应用程序:
点击按钮:
可以看到话和人交替显示,根据图片的大小,不规则的显示,这就是所谓的瀑布流形式:
这样看起来好像有点不舒服:我们可以使用addItemDecoration()方法给他加一个分割线,看起来好看一点:
在values文件下,修改decoration.xml,增加一个2dp的间距
修改WaterfallRecyclerViewActivity.java,如下,如何使用设置分割线在上面也有说过:
注意:分割线是RecyclerView的分割线,所以分割线应该是橙色的。
整体代码如下:
package com.example.yuan.e06_gridview.RecycleView;
import android.graphics.Rect;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;
import com.example.yuan.e05_listview.R;
public class WaterfallRecyclerViewActivity extends AppCompatActivity {
//声明引用
private RecyclerView mWaterfallRV;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_waterfall_recycler_view);
//获取控件对象
mWaterfallRV=findViewById(R.id.RV_waterfall_Id);
//设置布局管理器,两个参数,如果后面参数是垂直就代表第一个是几列,如果是水平,第一个就代表行数
mWaterfallRV.setLayoutManager(new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL));
//设置Adapter
mWaterfallRV.setAdapter(new WaterfallRecyclerViewAdapter(WaterfallRecyclerViewActivity.this));
//设置分割线
mWaterfallRV.addItemDecoration(new MyDecoration());
}
class MyDecoration extends RecyclerView.ItemDecoration {
//复写getItemOffsets方法
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
//设置距离为2dp
int distance = getResources().getDimensionPixelOffset(R.dimen.pirtureDistance);
//设置上下左右全部有2dp的分割线
outRect.set(distance, distance, distance,distance);
}
}
}
运行应用程序,可以看到上下左右全部都有1dp的分割线,现在看起来就层次分明了,还可以上下滑动:总共有30张图片
在上面的程序已经设置了点击事件了,所以点击会提示,点击的位置:
本例子完。
效果展示,如下:
是什么意思呢,大概解释一下,我们在RecyclerView本来只是引用一个布局文件来显示,比如里面有图片和文字结合,我们如果使用引用布局文件,就全部是显示这个布局文件有的内容,但是我们现在是向让他显示多个布局文件的东西,我们在一个RecyclerView,先引用布局A(只有文字),再引用布局B(只有图片),其实就像我们微信聊天页面一样,一会是文字,一会是图片,或语音或视频,使用RecyclerView就可以根据不同的ViewHolder在一个页面把不同类型的item显示出来。
我们使用RecyclerView,通过前面的例子知道,RecyclerView有很多种布局方式,有线性水平线性垂直,网格布局,瀑布流布局,我们使用它就得选择一个适合我们需要展示东西的性质,选一个简单的:
采用线性垂直的方式,然后引用两个ViewHolder.
直接在第一个例子的基础之上修改:
1.现在需要两个布局文件,第一个布局文件不修改。如下:
第二个布局文件,命名为:layout_linearrv_item2.xml,只有一个imageView控件
回到LinearAdapter.java文件中,去修改代码:
1.首先复写public int getItemViewType(int position)方法,此方法可以知道当前的item的位置,可以根据不同的位置设置不同的ViewHolder;
2.新增一个ViewHolder它对应的布局文件是:layout_linearrv_item2
3.修改onCreateViewHolder(ViewGroup parent, int viewType)方法
注意下面这几个地方都是需要修改的:
4.修改onBindViewHolder()方法,根据不同的ViewHolder显示不同的item.
加载的图片来自网络:
整体代码:
package com.example.yuan.e06_gridview.RecycleView;
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.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.example.yuan.e05_listview.R;
public class LinearAdapter extends RecyclerView.Adapter {
//声明引用
private Context mContext;
private LayoutInflater mLayoutInflater;
private OnItemClickListener mlistener;
//创建一个构造函数
public LinearAdapter(Context context,OnItemClickListener listener){
this.mContext=context;
//利用LayoutInflater把控件所在的布局文件加载到当前类当中
mLayoutInflater = LayoutInflater.from(context);
//从外部传进来一个OnItemClickListener子类的变量
this.mlistener=listener;
}
//此方法要返回一个ViewHolder
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType ==0){
return new LinearViewHolder(mLayoutInflater.inflate(R.layout.layout_linearrv_item,parent,false));
}else{
return new LinearViewHolder1(mLayoutInflater.inflate(R.layout.layout_linearrv_item2,parent,false));
}
}
//通过holder设置TextView的内容
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if (getItemViewType(position) ==0){
((LinearViewHolder)holder).textView.setText("Hello Yuan");
Glide.with(mContext).load("http://img.daimg.com/uploads/allimg/140729/3-140H9215513.jpg").into(((LinearViewHolder) holder).imageView);
}else{
Glide.with(mContext).load("http://img.article.pchome.net/01/57/12/92/pic_lib/wm/Jaguar-XFR-S-2014-widescreen-15.jpg").into(((LinearViewHolder1) holder).imageView);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mlistener.OnClick(position);
//点击后弹窗,显示点击位置
//Toast.makeText(mContext,"点击位置"+position,Toast.LENGTH_SHORT).show();
}
});
}
//获取位置
@Override
public int getItemViewType(int position) {
if(position % 2==0){ //位置是偶数
return 0;
}else { //位置是奇数
return 1;
}
}
@Override
public int getItemCount() {
return 25;
}
class LinearViewHolder extends RecyclerView.ViewHolder{
//声明layout_linearrv_item布局控件的变量
private TextView textView;
private ImageView imageView;
public LinearViewHolder(View itemView) {
super(itemView);
textView =(TextView) itemView.findViewById(R.id.TV_RVLinear_title1_Id);
imageView=(ImageView) itemView.findViewById(R.id.IV_Linear_picture1_Id);
}
}
class LinearViewHolder1 extends RecyclerView.ViewHolder{
//声明layout_linearrv_item布局控件的变量
private ImageView imageView;
public LinearViewHolder1(View itemView) {
super(itemView);
imageView=(ImageView) itemView.findViewById(R.id.IVLinear_picture_Id2);
}
}
//定义一个接口
public interface OnItemClickListener{
//接口默认都是抽象的方法,且类型都是public
void OnClick(int position);
}
}
已上代码部分完成,下面运行程序看一看
运行应用程序:
点击列表视图,可以看到两个布局切换,且偶数位是一张图片和文字结合的ViewHolder,奇数位只有一张图片:
设置了监听事件:
小结:在这基础上我们可以添加很多种ViewHolder显示,奇偶数位置,只是为了调试方便设置,在实际应用中,可能根据传进来的参数,或者不同类型指定不同的ViewHolder来显示,都是可可以的,多个ViewHolder同样可以是网格布局,瀑布流的形式。
所以说RecyclerView是灵活的,他可以做到ListView和GridView能做到的东西,也能做到他们做不到的东西,使用起来相对于前面两种稍微复杂一点点,但是灵活性还是很好的。