Android 图片库之Glide框架之RecycleView使用以及RecycleView详解
RecycleView简介
RecyclerView 是Android L版本中新添加的一个用来取代ListView的SDK,它的灵活性与可替代性比listview更好。
RecyclerView与ListView原理是类似的:都是仅仅维护少量的View并且可以展示大量的数据集。RecyclerView用以下两种方式简化了数据的展示和处理:
1.使用LayoutManager来确定每一个item的排列方式。
2.为增加和删除项目提供默认的动画效果。
你也可以定义你自己的LayoutManager和添加删除动画,RecyclerView项目结构如下:
Adapter:使用RecyclerView之前,你需要一个继承自RecyclerView.Adapter的适配器,作用是将数据与每一个item的界面进行绑定。
LayoutManager:用来确定每一个item如何进行排列摆放,何时展示和隐藏。回收或重用一个View的时候,LayoutManager会向适配器请求新的数据来替换旧的数据,这种机制避免了创建过多的View和频繁的调用findViewById方法(与ListView原理类似)。
下面讲述RecycleView+Glide框架的详细知识。
Glide框架详解:https://blog.csdn.net/weixin_37730482/article/category/6875816
代码以及说明
1.item布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dp">
<ImageView
android:id="@+id/gliderecycleview_circleimageview"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp"
android:scaleType="fitXY"
android:src="@mipmap/patient_ava" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_toRightOf="@+id/gliderecycleview_circleimageview">
<TextView
android:id="@+id/gliderecycleview_item_textview1"
android:layout_width="match_parent"
android:layout_height="30dp"
android:ellipsize="end"
android:gravity="center|left"
android:singleLine="true"
android:text="张三"
android:textColor="@color/colorPrimary"
android:textSize="14sp" />
<TextView
android:id="@+id/gliderecycleview_item_textview2"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_below="@+id/gliderecycleview_item_textview1"
android:ellipsize="end"
android:gravity="center|left"
android:singleLine="true"
android:text="这个人很懒什么也没留下"
android:textColor="@color/colorPrimary"
android:textSize="14sp" />
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_alignParentBottom="true"
android:background="@color/colorPrimary"/>
</RelativeLayout>
注意:
1.RecycleView的Item父布局高度不要写成match_parent。
2.可以在Item的布局中设置RecycleView的间隔线,这样就可以不用在Java代码中设置。
2.MainActivity布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/activity_gliderecycleview_toplayout"
android:layout_width="match_parent"
android:layout_height="70dp"
android:background="#339BFF">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
android:gravity="center"
android:text="RecyclerView页面"
android:textColor="#FFFFFF"
android:textSize="16sp" />
</RelativeLayout>
<LinearLayout
android:id="@+id/activity_gliderecycleview_linearlayout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_below="@+id/activity_gliderecycleview_toplayout"
android:orientation="horizontal"
android:weightSum="3">
<Button
android:id="@+id/activity_gliderecycleview_modebutton"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="列表" />
<Button
android:id="@+id/activity_gliderecycleview_addbutton"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:text="插入数据" />
<Button
android:id="@+id/activity_gliderecycleview_delbutton"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:text="删除数据" />
</LinearLayout>
<View
android:id="@+id/activity_gliderecycleview_view"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@+id/activity_gliderecycleview_linearlayout"
android:background="#CCCCCC" />
<android.support.v7.widget.RecyclerView
android:id="@+id/activity_gliderecycleview_recycleview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/activity_gliderecycleview_view">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
注意:
1.AndroidStudio中配置
implementation 'com.android.support:recyclerview-v7:27.1.1'
2.RecycleView所在包android.support.v7.widget.RecyclerView。
3.Adapter
public class GlideRecycleViewAdapter extends RecyclerView.Adapter<GlideRecycleViewAdapter.ViewHolder> {
private Activity activity;
private Context context;
private List<Student> list;
private LayoutInflater mInflater;
private RecycleViewAdapterInterface recycleViewAdapterInterface=null;
public void setRecycleViewItemClickAndLongClick(RecycleViewAdapterInterface recycleViewAdapterInterface){
this.recycleViewAdapterInterface=recycleViewAdapterInterface;
}
public GlideRecycleViewAdapter(Activity activity,Context context,List<Student> list){
this.activity=activity;
this.context=context;
this.list=list;
mInflater = LayoutInflater.from(context);
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view=mInflater.inflate(R.layout.gliderecycleview_item, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.textView1.setText(list.get(position).getName() + "【" + (position + 1) + "】");
holder.textView2.setText(list.get(position).getAge());
String ava = list.get(position).getAva();
if(!BooleanUtils.isEmpty(ava)){//头像不为空
//文字显示颜色
holder.textView1.setTextColor(context.getResources().getColor(R.color.colorPrimary));
holder.textView2.setTextColor(context.getResources().getColor(R.color.colorPrimary));
//获取 ava 对应的缓存文件
File file=new GlideImageUtils(context).getCacheFile(ava);
if(null!=file){//缓存文件不为空 直接加载file对应的图片
Glide.with(activity)
.load(file)
.placeholder(R.mipmap.patient_ava)
.error(R.mipmap.patient_ava)
.transform(new GlideCircleTransform(activity))
.into(holder.circleImageView);
}else{//缓存文件为空 加载url对应的图片
Glide.with(activity)
.load(ava)
.placeholder(R.mipmap.patient_ava)
.error(R.mipmap.patient_ava)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.transform(new GlideCircleTransform(activity))
.into(holder.circleImageView);
}
}else{//头像为空
//文字显示颜色
holder.textView1.setTextColor(context.getResources().getColor(R.color.colorAccent));
holder.textView2.setTextColor(context.getResources().getColor(R.color.colorAccent));
Glide.with(activity)
.load("http:www")
.placeholder(R.mipmap.patient_ava)
.error(R.mipmap.patient_ava)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.transform(new GlideCircleTransform(activity))
.into(holder.circleImageView);
}
/**
* 捕获RecycleView的Item点击以及长按事件
* */
final int clickposition=position;
//Item点击
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(null!=recycleViewAdapterInterface){
recycleViewAdapterInterface.OnItemCilck(v,clickposition);
}
}
});
//Item长按
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if(null!=recycleViewAdapterInterface){
recycleViewAdapterInterface.OnItemLongCilck(v,clickposition);
}
return true;
}
});
}
@Override
public int getItemCount() {
return list.size();
}
/**
* ViewHolder类
* */
class ViewHolder extends RecyclerView.ViewHolder{
private ImageView circleImageView;
private TextView textView1;
private TextView textView2;
public ViewHolder(View itemView) {
super(itemView);
circleImageView = itemView.findViewById(R.id.gliderecycleview_circleimageview);
textView1 = itemView.findViewById(R.id.gliderecycleview_item_textview1);
textView2 = itemView.findViewById(R.id.gliderecycleview_item_textview2);
}
}
/**
* 添加数据
* */
public void addData(Student student,int position) {
list.add(position, student);
notifyItemInserted(position);
notifyItemRangeChanged(position,list.size());
}
/**
* 删除数据
* */
public void removeData(int position) {
list.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position,list.size());
}
}
注意:
1.和ListView直接继承BaseAdapter不同。RecycleView的适配器
继承RecyclerView.Adapter<GlideRecycleViewAdapter.ViewHolder>。
2.至少需要重写三个方法。
onCreateViewHolder方法:引入Item布局。
onBindViewHolder方法:获取数值。
getItemCount方法:获取列表Item条数。
3.与ListView不同,RecycleView没有直接提供Item点击以及Item长按事件。需要自己写。
3.1.自定义接口
/**
* RecycleView Item点击以及长按事件
* */
public interface RecycleViewAdapterInterface {
void OnItemCilck(View view, int position);
void OnItemLongCilck(View view,int position);
}
3.2.Adapter中初始化以及暴露外部调用方法
3.2.1.初始化(onBindViewHolder方法中)
/**
* 捕获RecycleView的Item点击以及长按事件
* */
final int clickposition=position;
//Item点击
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(null!=recycleViewAdapterInterface){
recycleViewAdapterInterface.OnItemCilck(v,clickposition);
}
}
});
//Item长按
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if(null!=recycleViewAdapterInterface){
recycleViewAdapterInterface.OnItemLongCilck(v,clickposition);
}
return true;
}
});
3.2.2.外部调用(全局)
private RecycleViewAdapterInterface recycleViewAdapterInterface=null;
public void setRecycleViewItemClickAndLongClick(RecycleViewAdapterInterface recycleViewAdapterInterface){
this.recycleViewAdapterInterface=recycleViewAdapterInterface;
}
4.删除和添加数据
RecycleView删除添加数据非常方便。
/**
* 添加数据
* */
public void addData(Student student,int position) {
list.add(position, student);
notifyItemInserted(position);
notifyItemRangeChanged(position,list.size());
}
/**
* 删除数据
* */
public void removeData(int position) {
list.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position,list.size());
}
4.Activity中使用
public class GlideRecycleViewActivity extends AppCompatActivity implements View.OnClickListener {
private Button modebutton;
private Button addbutton;
private Button delbutton;
private RecyclerView recyclerview;
private GlideRecycleViewAdapter adapter;
private List<Student> list;
private int type = 0;
private int addposition = 0;
private int delposition = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gliderecycleview);
onWindowbar();
initData();
}
/**
* 赋值
*/
private void initData() {
modebutton = findViewById(R.id.activity_gliderecycleview_modebutton);
addbutton = findViewById(R.id.activity_gliderecycleview_addbutton);
delbutton = findViewById(R.id.activity_gliderecycleview_delbutton);
modebutton.setOnClickListener(this);
addbutton.setOnClickListener(this);
delbutton.setOnClickListener(this);
recyclerview = findViewById(R.id.activity_gliderecycleview_recycleview);
list = new ArrayList<>();
Student student1 = new Student();
student1.setName("詹姆斯");
student1.setAva("XXX");
student1.setAge(student1.getName() + ":很懒什么也没留下!");
Student student2 = new Student();
student2.setName("韦德");
student2.setAva("XXX");
student2.setAge(student2.getName() + ":很懒什么也没留下!");
Student student3 = new Student();
student3.setName("山东鲁能");
student3.setAva("XXX");
student3.setAge(student3.getName() + ":很懒什么也没留下!");
Student student4 = new Student();
student4.setName("保罗");
student4.setAva("XXX");
student4.setAge(student4.getName() + ":很懒什么也没留下!");
Student student5 = new Student();
student5.setName("安东尼");
student5.setAva("XXX");
student5.setAge(student5.getName() + ":很懒什么也没留下!");
Student student6 = new Student();
student6.setName("蒿俊闵");
student6.setAva("XXX");
student6.setAge(student6.getName() + ":很懒什么也没留下!");
Student student7 = new Student();
student7.setName("李霄鹏");
student7.setAva("");
student7.setAge(student7.getName() + ":没有上传头像!");
for (int i = 0; i < 30; i++) {
list.add(student1);
list.add(student2);
list.add(student3);
list.add(student4);
list.add(student5);
list.add(student6);
list.add(student7);
}
//2.设置LinearLayoutManager ListView
recyclerview.setLayoutManager(new LinearLayoutManager(this));
//3.设置ItemAnimator
recyclerview.setItemAnimator(new DefaultItemAnimator());
//4.设置固定大小
recyclerview.setHasFixedSize(true);
adapter = new GlideRecycleViewAdapter(this, this, list);
recyclerview.setAdapter(adapter);
/**
* RecycleView滚动监听是开始加载Glide还是暂停加载Glide
* */
recyclerview.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
switch (newState) {
case SCROLL_STATE_SETTLING://滚动
Glide.with(GlideRecycleViewActivity.this).pauseRequests();//停止Glide加载图片
break;
case SCROLL_STATE_DRAGGING://拖动
Glide.with(GlideRecycleViewActivity.this).pauseRequests();//停止Glide加载图片
break;
case SCROLL_STATE_IDLE://空闲
Glide.with(GlideRecycleViewActivity.this).resumeRequests();//开始Glide加载图片
break;
default://其他
Glide.with(GlideRecycleViewActivity.this).pauseRequests();//停止Glide加载图片
break;
}
adapter.notifyDataSetChanged();
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
/**
* Item点击以及长按监听
* */
if (null != adapter) {
adapter.setRecycleViewItemClickAndLongClick(new RecycleViewAdapterInterface() {
@Override
public void OnItemCilck(View view, int position) {
if (null != list) {
String name = list.get(position).getName();
Toast.makeText(GlideRecycleViewActivity.this, "点击:" + name, Toast.LENGTH_SHORT).show();
}
}
@Override
public void OnItemLongCilck(View view, int position) {
if (null != list) {
String name = list.get(position).getName();
Toast.makeText(GlideRecycleViewActivity.this, "长按:" + name, Toast.LENGTH_SHORT).show();
}
}
});
}
}
/**
* 各种点击事件的View
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.activity_gliderecycleview_modebutton://变换模式
type++;
if (type == 0) {//列表
modebutton.setText("列表");
recyclerview.setLayoutManager(new LinearLayoutManager(GlideRecycleViewActivity.this));
} else if (type == 1) {//网格
modebutton.setText("网格");
recyclerview.setLayoutManager(new GridLayoutManager(GlideRecycleViewActivity.this, 4));
} else if (type == 2) {//横向列表
modebutton.setText("横向列表");
recyclerview.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL));
} else {
type = 0;
modebutton.setText("列表");
recyclerview.setLayoutManager(new LinearLayoutManager(GlideRecycleViewActivity.this));
}
break;
case R.id.activity_gliderecycleview_addbutton://添加数据
if (null != adapter) {
addposition++;
Student student = new Student();
student.setName("詹姆斯" + addposition);
student.setAva("http://cdspres.oss-cn-beijing.aliyuncs.com/avatar/80366a04e7874e4fa04a6ef8e68ab3751525391386176.png");
student.setAge(student.getName() + ":很懒什么也没留下!");
adapter.addData(student, addposition);
}
break;
case R.id.activity_gliderecycleview_delbutton://删除数据
if (null != adapter) {
delposition++;
adapter.removeData(delposition);
}
break;
default:
break;
}
}
/**
* onKeyDown方法
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
finish();
overridePendingTransition(0, R.anim.activity_right_open);
return false;
}
return super.onKeyDown(keyCode, event);
}
}
注意:
1.RecycleView的滚动事件最好是这样添加。
recyclerview.addOnScrollListener(new RecyclerView.OnScrollListener())
因为
recyclerview.setOnScrollListener(new RecyclerView.OnScrollListener())
可能会出现空指针,且已过期。
另外RecycleView滚动事件 状态
SCROLL_STATE_SETTLING:滚动
SCROLL_STATE_DRAGGING:拖动
SCROLL_STATE_IDLE:空闲
2.目前SDK中提供了三种自带的LayoutManager
LinearLayoutManager:ListView列表
GridLayoutManager:GridView列表
StaggeredGridLayoutManager:纵向列表
recyclerview.setLayoutManager(new LinearLayoutManager(this));
recyclerview.setLayoutManager(new GridLayoutManager(GlideRecycleViewActivity.this, 4));//4:GridView一行显示几个Item
recyclerview.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL));2:纵向列表一页显示几行item
3.可设置RecycleView的Animator(动画效果,这里以默认为例)
recyclerview.setItemAnimator(new DefaultItemAnimator());
4.获取在Adapter中设置的RecycleView的Item点击以及长按事件。
/**
* Item点击以及长按监听
* */
if (null != adapter) {
adapter.setRecycleViewItemClickAndLongClick(new RecycleViewAdapterInterface() {
@Override
public void OnItemCilck(View view, int position) {
if (null != list) {
String name = list.get(position).getName();
Toast.makeText(GlideRecycleViewActivity.this, "点击:" + name, Toast.LENGTH_SHORT).show();
}
}
@Override
public void OnItemLongCilck(View view, int position) {
if (null != list) {
String name = list.get(position).getName();
Toast.makeText(GlideRecycleViewActivity.this, "长按:" + name, Toast.LENGTH_SHORT).show();
}
}
});
}
上一篇: js面试题