Android06之RecyclerView详解
上一次我们讲解了ListView和GridView两种控件的用法,这一次我们讲解新的控件RecyclerView,这个控件可以说是前两个控件的集成版本,并且拥有更多的功能。下面我们进行详细的讲解。
RecyclerView能够灵活的实现大数据集的展现,视图的复用管理比ListView好,能够展示列表、网格、瀑布流等形式,且不同的ViewHolder能够实现item多元化的功能。
接下来我们主要讲解RecyclerView的几种用法,包括:①列表视图;②水平滚动;③网格视图;④瀑布流。
我们新建recyclerview包,里面新建的类如下图所示:
其中RecyclerViewActivity相当于一个总的类,里面的代码主要用于按钮的跳转,我们先展示与其对应的布局文件activity_recycler_view.xml的代码,如下:
<?xml version="1.0" encoding="utf-8"?>
RecyclerViewActivity的代码如下:
package com.autumn.recyclerview;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import com.autumn.R;public class RecyclerViewActivity extends AppCompatActivity { @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recycler_view); //用于列表视图按钮的页面跳转 Button btnLinear = findViewById(R.id.btn_linear); btnLinear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(RecyclerViewActivity.this,LinearRecyclerViewActivity.class); startActivity(intent); } }); //用于水平滚动按钮的页面跳转 Button btnHor = findViewById(R.id.btn_hor); btnHor.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(RecyclerViewActivity.this,HorRecyclerViewActivity.class); startActivity(intent); } }); //用于网格视图按钮的页面跳转 Button btnGrid = findViewById(R.id.btn_grid); btnGrid.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(RecyclerViewActivity.this,GridRecyclerViewActivity.class); startActivity(intent); } }); //用于瀑布流按钮的页面跳转 Button btnPu = findViewById(R.id.btn_pu); btnPu.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(RecyclerViewActivity.this,PuRecyclerViewActivity.class); startActivity(intent); } }); }}
主界面截图如下:
接下来我们就要处理各个按钮的点击事件了,我们先处理列表视图按钮,我们新建LinearRecyclerViewActivity活动类,附带的activity_linear_recycler_view.xml文件如下:
<?xml version="1.0" encoding="utf-8"?>
这里我们只引入一个RecyclerView的控件,具体样式我们会另外新建xml文件的。我们在layout下新建两个xml文件,分别是layout_linear_item.xml和layout_linear_item2.xml文件,代码分别如下所示:
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
经过对比我们可以发现,第一个仅仅包含文本,第二个则包含文本和图片,与之前类似,我们需要创建适配器LinearAdapter,代码如下:
package com.autumn.recyclerview;import android.content.Context;import android.support.annotation.NonNull;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.autumn.R;public class LinearAdapter extends RecyclerView.Adapter { private Context context; private OnItemClickListener listener; public LinearAdapter(Context context,OnItemClickListener listener){ this.context = context; this.listener = listener; } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { //返回的是RecyclerView单项item的布局 if(i == 0) return new LinearViewHolder(LayoutInflater.from(context).inflate(R.layout.layout_linear_item,viewGroup,false)); else return new LinearViewHolder2(LayoutInflater.from(context).inflate(R.layout.layout_linear_item2,viewGroup,false)); } //给viewHolder中控件进行赋值 @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, final int position) { //不同的viewHolder呈现出来的效果 if(getItemViewType(position) == 0){ ((LinearViewHolder)viewHolder).textView.setText("以梦为马,不负韶华"); }else{ ((LinearViewHolder2)viewHolder).imageView.setImageResource(R.drawable.beauty_girl); ((LinearViewHolder2)viewHolder).textView.setText("面朝大海,春暖花开"); } //设置点击监听事件 viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listener.onClick(position); //Toast.makeText(context,"click..."+position,Toast.LENGTH_SHORT).show(); } }); } @Override public int getItemCount() { return 20; } public int getItemViewType(int pos) { if(pos %2 == 0) return 0; else return 1; } //自定义内部类LinearViewHolder class LinearViewHolder extends RecyclerView.ViewHolder { private TextView textView; public LinearViewHolder(@NonNull View itemView) { super(itemView); textView = itemView.findViewById(R.id.tv_title); } } class LinearViewHolder2 extends RecyclerView.ViewHolder { private TextView textView; private ImageView imageView; public LinearViewHolder2(@NonNull View itemView) { super(itemView); textView = itemView.findViewById(R.id.tv_title); imageView = itemView.findViewById(R.id.iv); } } public interface OnItemClickListener { void onClick(int pos); }}
RecyclerView中没有item监听事件,所以我们需要自定义接口,然后我们也定义了两个内部类ViewHolder,分别用于加载两个布局文件,这里我们用item的下标进行判断加载了哪一种布局,pos为偶数,则加载第一种布局;pos为奇数,则加载第二种布局。其中onBindViewHolder方法主要用于给控件进行赋值,getItemCount方法用于返回Item的数量,这里我们设置为常量20。
LinearRecyclerViewActivity则主要用于设置布局样式,设置适配器以及添加分隔线。代码如下:
package com.autumn.recyclerview;import android.graphics.Rect;import android.support.annotation.NonNull;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.autumn.R;public class LinearRecyclerViewActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_linear_recycler_view); RecyclerView recyclerView = findViewById(R.id.rv_main); recyclerView.setLayoutManager(new LinearLayoutManager(LinearRecyclerViewActivity.this)); recyclerView.addItemDecoration(new MyDecoration()); //设置适配器Adapter,其中监听事件方法需要自己定义 recyclerView.setAdapter(new LinearAdapter(LinearRecyclerViewActivity.this, new LinearAdapter.OnItemClickListener() { @Override public void onClick(int pos) { Toast.makeText(LinearRecyclerViewActivity.this,"click..."+pos,Toast.LENGTH_SHORT).show(); } })); } //定义内部类MyDecoration,并设置分隔线 class MyDecoration extends RecyclerView.ItemDecoration { @Override public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); outRect.set(0,0,0,getResources().getDimensionPixelOffset(R.dimen.dividerHeight)); } }}
这里我们定义了内部类MyDecoration,主要用于item之间的分隔线,我们在values文件夹下新建dimens.xml文件,代码如下:
<?xml version="1.0" encoding="utf-8"?> 4dp
到这儿一步列表视图就好了,运行截图如下:
我们添加了点击事件,默认下标从0开始。
接下来到了水平滚动了,我们新建HorRecyclerViewActivity活动类,附带的activity_hor_recycler_view.xml布局文件代码如下:
<?xml version="1.0" encoding="utf-8"?>
这里我们和上面一样,只加入了一个RecyclerView的控件。具体的样式布局在layout_hor_item.xml文件中,代码如下:
<?xml version="1.0" encoding="utf-8"?>
然后操作和上面差不多,我们新建适配器HorAdapter,代码如下:
package com.autumn.recyclerview;import android.content.Context;import android.support.annotation.NonNull;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import android.widget.Toast;import com.autumn.R;public class HorAdapter extends RecyclerView.Adapter { private Context context; private OnItemClickListener clickListener; public HorAdapter(Context context,OnItemClickListener listener){ this.context = context; this.clickListener = listener; } @NonNull @Override public HorAdapter.LinearViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { //返回的是RecyclerView单项item的布局 return new LinearViewHolder(LayoutInflater.from(context).inflate(R.layout.layout_hor_item,viewGroup,false)); } //给viewHolder中控件textView进行赋值 @Override public void onBindViewHolder(@NonNull HorAdapter.LinearViewHolder viewHolder, final int position) { viewHolder.textView.setText("lsq"); viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clickListener.OnClick(position); //Toast.makeText(context,"click..."+position,Toast.LENGTH_SHORT).show(); } }); } @Override public int getItemCount() { return 20; } //自定义内部类LinearViewHolder class LinearViewHolder extends RecyclerView.ViewHolder { private TextView textView; public LinearViewHolder(@NonNull View itemView) { super(itemView); textView = itemView.findViewById(R.id.tv_title); } } public interface OnItemClickListener { void OnClick(int pos); }}
具体解释就不多说了,和前面一个差不多。接下来就是完善HorReyclerViewActivity的代码了,如下所示:
package com.autumn.recyclerview;import android.graphics.Rect;import android.support.annotation.NonNull;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.autumn.R;public class HorRecyclerViewActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_hor_recycler_view); RecyclerView RvHor = findViewById(R.id.rv_hor); LinearLayoutManager manager = new LinearLayoutManager(HorRecyclerViewActivity.this); manager.setOrientation(LinearLayoutManager.HORIZONTAL); RvHor.setLayoutManager(manager); RvHor.addItemDecoration(new MyDecoration()); RvHor.setAdapter(new HorAdapter(HorRecyclerViewActivity.this, new HorAdapter.OnItemClickListener() { @Override public void OnClick(int pos) { Toast.makeText(HorRecyclerViewActivity.this,"click..."+pos,Toast.LENGTH_SHORT).show(); } })); } //内部装饰类(用于加上分隔线) class MyDecoration extends RecyclerView.ItemDecoration { @Override public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); outRect.set(0,0,getResources().getDimensionPixelOffset(R.dimen.dividerHeight),0); } }}
这里我们添加了水平的分割线,并添加了点击事件,运行截图如下所示:
接下来就到了网格视图了,同理,新建GridRecyclerViewActivity,同时新建activity_grid_recycler_view.xml,代码如下:
<?xml version="1.0" encoding="utf-8"?>
具体的布局文件为layout_grid_recycler_view.xml,代码如下:
<?xml version="1.0" encoding="utf-8"?>
我们仅仅添加了一个TextView控件,用于简单的测试,接下来我们新建GridAdapter适配器,代码如下:
package com.autumn.recyclerview;import android.content.Context;import android.support.annotation.NonNull;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import com.autumn.R;public class GridAdapter extends RecyclerView.Adapter { private Context context; private OnItemClickListener clickListener; public GridAdapter(Context context, OnItemClickListener listener){ this.context = context; this.clickListener = listener; } @NonNull @Override public GridAdapter.LinearViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { //返回的是GridRecyclerView单项item的布局 return new LinearViewHolder(LayoutInflater.from(context).inflate(R.layout.layout_grid_recycler_item,viewGroup,false)); } //给viewHolder中控件textView进行赋值 @Override public void onBindViewHolder(@NonNull GridAdapter.LinearViewHolder viewHolder, final int position) { viewHolder.textView.setText("Hello"); viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clickListener.OnClick(position); //Toast.makeText(context,"click..."+position,Toast.LENGTH_SHORT).show(); } }); } @Override public int getItemCount() { return 60; } //自定义内部类LinearViewHolder class LinearViewHolder extends RecyclerView.ViewHolder { private TextView textView; public LinearViewHolder(@NonNull View itemView) { super(itemView); textView = itemView.findViewById(R.id.tv_title); } } public interface OnItemClickListener { void OnClick(int pos); }}
适配器写好之后,接下来就到了GridRecyclerViewActivty了,代码如下:
package com.autumn.recyclerview;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.support.v7.widget.GridLayoutManager;import android.support.v7.widget.RecyclerView;import android.widget.Toast;import com.autumn.R;public class GridRecyclerViewActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_grid_recycler_view); RecyclerView RvGrid = findViewById(R.id.rv_grid); //一行展示3个Item RvGrid.setLayoutManager(new GridLayoutManager(GridRecyclerViewActivity.this,3)); RvGrid.setAdapter(new GridAdapter(GridRecyclerViewActivity.this, new GridAdapter.OnItemClickListener() { @Override public void OnClick(int pos) { Toast.makeText(GridRecyclerViewActivity.this,"click..."+pos,Toast.LENGTH_SHORT).show(); } })); }}
运行的效果如下图所示:
同样的,我们在GridLayoutManager中设置一行显示3个Item,并添加了监听事件。
接下来我们介绍最后一个版块,即瀑布流的布局。
我们新建PuRecyclerViewActivity,然后在layout下新建activity_pu_recycler_view.xml文件,代码如下:
<?xml version="1.0" encoding="utf-8"?>
具体的布局样式我们重新定义,新建layout_staggered_grid_recycler_view.xml文件,代码如下:
<?xml version="1.0" encoding="utf-8"?>
然后是创建适配器StaggeredGridAdapter,具体代码如下:
package com.autumn.recyclerview;import android.content.Context;import android.support.annotation.NonNull;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import com.autumn.R;public class StaggeredGridAdapter extends RecyclerView.Adapter { private Context context; private OnItemClickListener clickListener; public StaggeredGridAdapter(Context context, OnItemClickListener listener){ this.context = context; this.clickListener = listener; } @NonNull @Override public StaggeredGridAdapter.LinearViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { //返回的是GridRecyclerView单项item的布局 return new LinearViewHolder(LayoutInflater.from(context).inflate(R.layout.layout_staggered_grid_recycler_item,viewGroup,false)); } //给viewHolder中控件textView进行赋值 @Override public void onBindViewHolder(@NonNull StaggeredGridAdapter.LinearViewHolder viewHolder, final int position) { if(position % 2 != 0){ viewHolder.imageView.setImageResource(R.drawable.image1); }else { viewHolder.imageView.setImageResource(R.drawable.image2); } viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clickListener.OnClick(position); //Toast.makeText(context,"click..."+position,Toast.LENGTH_SHORT).show(); } }); } @Override public int getItemCount() { return 30; } //自定义内部类LinearViewHolder class LinearViewHolder extends RecyclerView.ViewHolder { private ImageView imageView; public LinearViewHolder(@NonNull View itemView) { super(itemView); imageView = itemView.findViewById(R.id.iv); } } public interface OnItemClickListener { void OnClick(int pos); }}
这里的和第一个LinearAdapter差不多,position为奇数加载图片1,为偶数加载图片2,我们这里挑了两张图片的长宽相差很大,以此显示出交错感,然后PuRecyclerViewActivity的代码如下:
package com.autumn.recyclerview;import android.graphics.Rect;import android.support.annotation.NonNull;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 android.widget.Toast;import com.autumn.R;public class PuRecyclerViewActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_pu_recycler_view); RecyclerView RvPu = findViewById(R.id.rv_pu); //垂直有两列 RvPu.setLayoutManager(new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL)); RvPu.addItemDecoration(new MyDecoration()); RvPu.setAdapter(new StaggeredGridAdapter(PuRecyclerViewActivity.this, new StaggeredGridAdapter.OnItemClickListener() { @Override public void OnClick(int pos) { Toast.makeText(PuRecyclerViewActivity.this,"click:"+pos,Toast.LENGTH_SHORT).show(); } })); } //内部类,用于创建分割线 class MyDecoration extends RecyclerView.ItemDecoration { @Override public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); int gap = getResources().getDimensionPixelSize(R.dimen.dividerHeight); outRect.set(gap,gap,gap,gap); } }}
运行截图如下所示:
好了,有关RecyclerView的讲解就到这里了,全部的代码(包括之前的)我已经上传到GitHub上,链接为https://github.com/229394/AndroidBasic,欢迎大家Star!
更多相关文章
- 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
- RN 与 Android(安卓)代码交互
- 一步步实现 仿制Android(安卓)LOL多玩盒子(四) 自定义AlertDialo
- Cocos2d-x +Android(安卓)+ Windows 7环境配置
- android 内存泄露之jni local reference table overflow (max=51
- 说说Android(安卓)两种为自定义组件添加属性的使用方法和区别
- Android(安卓)4.4 Graphic系统详解(4)HWUI概述
- android 模拟器和PC用sockets通讯
- Android应用开发笔记(12):Android应用的自动升级、更新模块的实现