Android笔记—UI-RecyclerView
资料来源如下
- 第一行代码(第二版)
- RecyclerView使用详解—六和敬
- RecyclerView使用介绍— Jin Yudong
- Android RecyclerView 使用完全解析 体验艺术般的控件—鸿洋_
- 创建列表与卡片—Android Developer
编程环境
- Android Studio 2.2.3
导语
- RecyclerView内容较ListView更多,初期只能更新一些基础内容,高级的用法随时更新,长期跟进
简介
- RecyclerView是用于取代ListView的组件,第一次出现是在2014年google I/O大会,内置在是Android L及以上版本的SDK中。
- 对比与ListView,RecyclerView弥补了ListView中的效率问题,同时支持更多的显示效果,代码逻辑更为清晰
基本使用步骤
- RecyclerView定义在support库中,使用RecyclerView之前必须在添加依赖
- build.gradle中添加
compile 'com.android.support:recyclerview-v7:25.1.0'
RecyclerView项目结构如下:
要使用RecyclerView,需要指定一个Adapter适配器和一个LayoutManager布局管理器
Adapter适配器:作用与ListView中使用的Adapter相同,都是将数据与对应item的界面进行绑定
所不同的是:RecyclerView中适配器必须继承自RecyclerView.Adapter,且 强制使用了ViewHolderLayoutManager布局管理器:每一个item如何进行排列,何时展示和隐藏。
重用View时,LayoutManager会向Adapter适配器请求新的数据替换旧的数据,避免了View的冗余和频繁调用findViewByIdLayoutManager的引入 使得各种布局排列编写,变的格外容易,这也是RecyclerView优于ListView的一个地方
目前RecyclerView 内置3种LayoutManager:
- LinearLayoutManager 横向/竖向布局
- GridLayoutManager 网格布局
- StaggeredGridLayoutManager 瀑布流布局
MainActivity中 RecyclerView 设置
创建RecyclerView对象
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycle_view);
设置LayoutManager显示规则
设置适配器
recyclerview.setAdapter(adapter);
简单实例
由一个简单的实例+详细分析
添加依赖
打开app/build.gradle文件,在dependencies闭包下添加依赖库
版本与你工程的com.android.support:appcompat-v7:25.1.0
版本对应1
compile 'com.android.support:recyclerview-v7:25.1.0'
之后AndroidStudio会开始同步
添加RecyclerView到xml文件,基本与ListView一致,不过RecyclerView并非内置在SDK中,这里需要写出完整的包路径
1
2
3
4
5<android.support.v7.widget.RecyclerView
android:id="@+id/recycle_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>要展示的依旧是水果+图片形式,
图片资源在第一行代码第二版源码 /chapter3/ListViewTest\app\src\main\res\drawable-hdpi下,同时将Fruit类和fruit_item.xml一并复制,这里给出两者源码,不再加分析_- Fruit类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class Fruit {
private String name;
private int imageId;
public Fruit(String name, int imageId) {
this.name = name;
this.imageId = imageId;
}
public String getName() {
return name;
}
public int getImageId() {
return imageId;
}
} - fruit_item.xml _
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/fruit_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/fruit_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp" />
</LinearLayout>
- Fruit类
准备RecyclerView适配器,适配器需要继承自 RecyclerView.Adapter,将泛型指定为 .ViewHolder,(ViewHolder为在适配器的一个内部类),并重写3个方法
1
2
3public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType)//创建返回ViewHolder实例
public void onBindViewHolder(ViewHolder holder,int pisition)//数据与界面绑定
public int getItemCount() // 返回数据的数量新建 FruitAdapter 继承自 RecyclerView.Adapter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49//继承自RecyclerView.Adapter,泛型为 FruitAdapter .ViewHolder
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
//私有Fruit列表
private List<Fruit> mFruitList;
//新建内部类ViewHolder继承自RecyclerView.ViewHolde有每个Item的的所有界面元素
static class ViewHolder extends RecyclerView.ViewHolder{
ImageView fruitImage;
TextView fruitName;
//ViewHolder构造函数,传入View,通常为RecyclerView子项的外层布局(本例为fruit_item.xml)
public ViewHolder(View view){
super(view);
//findViewById获取 Image/Name实例
fruitImage = (ImageView)view.findViewById(R.id.fruit_image);
fruitName = (TextView)view.findViewById(R.id.fruit_name);
}
}
//FruitAdapter构造函数,将数据源传入全局变量mFruitList
public FruitAdapter(List<Fruit>fruitList){
mFruitList = fruitList;
}
//创建ViewHolder实例
public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType){
//加载布局文件
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);
//调用ViewHolder构造函数
ViewHolder holder = new ViewHolder(view);
//返回ViewHolder实例
return holder;
}
//对 RecyclerView子项进行赋值,有新的子项进入屏幕显示范围时调用
public void onBindViewHolder(ViewHolder holder,int pisition){
Fruit fruit = mFruitList.get(pisition);
holder.fruitImage.setImageResource(fruit.getImageId());
holder.fruitName.setText(fruit.getName());
}
//返回 RecyclerView子项数量
public int getItemCount(){
return mFruitList.size();
}
}MainActivity中使用RecyclerView
创建RecyclerView对象
设置LayoutManager显示规则(默认竖向滚动)
设置适配器
代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50public class MainActivity extends AppCompatActivity {
//私有列表
private List<Fruit> fruitList = new ArrayList<Fruit>();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化Fruits数据
initFruits();
//获取RecyclerView实例
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycle_view);
//创建LinearLayoutManager,并设置入recyclerView
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
//新建适配器,并传入
FruitAdapter adapter = new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
}
//初始化Fruits类
private void initFruits() {
//循环两遍 怕占不满屏幕
for (int i = 0; i < 2; i++) {
Fruit apple = new Fruit("Apple", R.drawable.apple_pic);
fruitList.add(apple);
Fruit banana = new Fruit("Banana", R.drawable.banana_pic);
fruitList.add(banana);
Fruit orange = new Fruit("Orange", R.drawable.orange_pic);
fruitList.add(orange);
Fruit watermelon = new Fruit("Watermelon", R.drawable.watermelon_pic);
fruitList.add(watermelon);
Fruit pear = new Fruit("Pear", R.drawable.pear_pic);
fruitList.add(pear);
Fruit grape = new Fruit("Grape", R.drawable.grape_pic);
fruitList.add(grape);
Fruit pineapple = new Fruit("Pineapple", R.drawable.pineapple_pic);
fruitList.add(pineapple);
Fruit strawberry = new Fruit("Strawberry", R.drawable.strawberry_pic);
fruitList.add(strawberry);
Fruit cherry = new Fruit("Cherry", R.drawable.cherry_pic);
fruitList.add(cherry);
Fruit mango = new Fruit("Mango", R.drawable.mango_pic);
fruitList.add(mango);
}
}
}这样最简单的 RecyclerView 就搭建完了效果如下
代码比ListView稍多,但是逻辑比较清晰。
横向/瀑布流/网格布局
- 只需要设置相应LayoutManager即可 /手动滑稽
横向
在 LinearLayoutManager 中修改几行代码即可
修改 LinearLayoutManager 代码,添加一行,搞定!
1
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
当然需要简单修改一下item的布局文件,LinearLayout改为垂直排列,宽度固定100dp,图片/文字居中
效果如下
瀑布流
这需要 StaggeredGridLayoutManager 布局管理器,可以 竖向/横向 滚动
代码如下
1
2//瀑布流布局,3行,竖向
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);调整布局文件,效果如下
网格
- 这需要 GridLayoutManager 布局管理器
- 代码如下
1
2//网格布局,两行
GridLayoutManager layoutManager = new GridLayoutManager(this,3); - 调整布局文件后,效果如下
注册点击事件
- RecyclerView 中并没有提供注册监听器的方法,需要子项View自行注册
- 部分代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35static class ViewHolder extends RecyclerView.ViewHolder {
View fruitView;
ImageView fruitImage;
TextView fruitName;
public ViewHolder(View view) {
super(view);
fruitView = view;
fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
fruitName = (TextView) view.findViewById(R.id.fruit_name);
}
}
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
holder.fruitView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int position = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Toast.makeText(v.getContext(), "you clicked view " + fruit.getName(), Toast.LENGTH_SHORT).show();
}
});
holder.fruitImage.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int position = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Toast.makeText(v.getContext(), "you clicked image " + fruit.getName(), Toast.LENGTH_SHORT).show();
}
});
return holder;
}