最近工作有了着落,毕业论文中期答辩也结束了,比较清闲,可以有时间对之前学的一些知识做一些总结。
在去年的谷歌 I/O大会上,谷歌发布了Android5.0,称之为L版本。相对于以前的版本这是一个非常大的进步,而且我十分赞同谷歌的这一做法。不论是开发者还是消费者都从中收益。谷歌开放了两个全新的视图:RecyclerView和GardView。而这篇博客主要介绍的是RecyclerView。
一、概述
谷歌在是这样描述RecyclerView的:“A flexible view for providing a limited window into a large data set.”大概的意思是:一个用于在有限的窗口中展示大量数据集的控件。这样的功能在之前版本中的ListView和GridView也可以实现。那么有了ListView、GridView为什么还需要RecyclerView这样的控件呢?整体上看RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现自己想要的效果。
- 显示的方式,通过布局管理器LayoutManager(默认是垂直的,可以改变为水平的)
- 控制Item间的间隔(可绘制),通过ItemDecoration类来实现
- 控制Item增删的动画,通过ItemAnimator
- 控制点击、长按事件,需要自己来实现
RecyclerView和ListView一样也实现了复用机制,它不仅可以减少CPU不断inflate View的开销,而且可以节省缓存View的内存开销。
二、基本使用
RecylerView作为support-library发布出来的,这样我们可以在更低的Android版本上使用这个新视图,首先我们要知道怎样找到这个引用的包,在Android Studio上有以下两种方法:
1. 在Android Studio中打开Android SDK Manager然后更新Extras下的Android Support Library即可。
- 在项目中的build.gradle文件中添加引用,给出我的项目中的gradle截图
使用一个RecylerView,主要需要以下几步:
// 获取RecyclerView对象
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
// 创建线性布局管理器(默认是垂直方向)
layoutManager = new LinearLayoutManager(this);
// 将布局管理器设置为水平方向的
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
// 为RecyclerView指定布局管理对象
recyclerView.setLayoutManager(layoutManager);
// 设置Item增加、移除动画
recyclerView.setItemAnimator(new DefaultItemAnimator());
// 添加分割线
recyclerView.addItemDecoration(new MyItemDecoration(this));
myRecyclerAdapter = new MyRecyclerAdapter();
// 设置adapter
recyclerView.setAdapter(myRecyclerAdapter);
相比较于ListView的代码,ListView可能只需要去设置一个adapter就能正常使用了。而RecyclerView和ListView不一样的是,RecyclerView不再负责Item的摆放等显示方面的功能。所有和布局、绘制等方面的工作Google都其拆分成不同的类进行管理。所以开发者可以自定义各种各样满足定制需求的的功能类。
下面是一些和RecyclerView相关的非常重要的类列表。
- Activity
package com.recyclerview;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity implements View.OnClickListener {
MyRecyclerAdapter myRecyclerAdapter;
LinearLayoutManager layoutManager;
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取RecyclerView对象
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
// 创建线性布局管理器(默认是垂直方向)
layoutManager = new LinearLayoutManager(this);
// 将布局管理器设置为水平方向的
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
// 为RecyclerView指定布局管理对象
recyclerView.setLayoutManager(layoutManager);
// 设置Item增加、移除动画
recyclerView.setItemAnimator(new DefaultItemAnimator());
// 添加分割线
recyclerView.addItemDecoration(new MyItemDecoration(this));
myRecyclerAdapter = new MyRecyclerAdapter();
// 设置adapter
recyclerView.setAdapter(myRecyclerAdapter);
/**
* 删除和增加item
*/
Button addBtn, removeBtn;
addBtn = (Button) findViewById(R.id.add);
removeBtn = (Button) findViewById(R.id.remove);
addBtn.setOnClickListener(this);
removeBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.add://添加item
myRecyclerAdapter.addItem(1);
break;
case R.id.remove://删除item
myRecyclerAdapter.removeData(1);
break;
}
}
}
- Activity布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="120dp"
android:scrollbars="horizontal"
tools:listitem="@layout/list_basic_item"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/add"
style="@style/button_type"
android:layout_width="0dp"
android:layout_weight="1"
android:text="添加"/>
<Button
android:id="@+id/remove"
style="@style/button_type"
android:layout_width="0dp"
android:layout_weight="1"
android:text="删除"/>
</LinearLayout>
</LinearLayout>
- Item的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/textViewSample"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_gravity="center_horizontal"
android:fontFamily="sans-serif-light"
android:textSize="20sp"
tools:text="Sample text"/>
</LinearLayout>
- MyItemDecoration是继承RecyclerView.ItemDecoration的一个类
通过ItemDecoration可以使各个Item在视觉上相互分开,其实和ListView的Divider很像。ItemDecoration并不是RecyclerView必须设置的,开发者可以不设置或者设置多个Decoration。RecyclerView会遍历所有的ItemDecoration并调用各自的绘图方法。
继承ItemDecoration需要实现以下三个方法:
public void onDraw(Canvas c,RecyclerView parent,RecyclerView.State state)
public void getItemOffset(Rect outRect,int itemPosition,RecyclerView parent)
LayoutManager会调用getItemOffset方法来计算每个Item的Decoration合适的尺寸。
package com.recyclerview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class MyItemDecoration extends RecyclerView.ItemDecoration {
// 默认分隔条Drawable资源的ID
private static final int[] ATTRS = {android.R.attr.listDivider};
// 分隔条Drawable对象
private Drawable mDivider;
public MyItemDecoration(Context context) {
TypedArray a = context.obtainStyledAttributes(ATTRS);
// 获取系统提供的分隔条Drawable对象
mDivider = a.getDrawable(0);
// 回收TypedArray所占用的空间
a.recycle();
}
// 在该方法中绘制了所有列表项之间的分隔条
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
int top = parent.getPaddingTop();
int bottom = parent.getHeight() - parent.getPaddingBottom();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
int left = child.getRight() + layoutParams.rightMargin;
int right = left + mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}
- MyRecyclerAdapter是继承 RecyclerView.Adapter的一个类
Adapter负责扮演两个角色:不仅为底部数据提供支持而且还负责为数据创建合适的视图。Adapter适用在Android很多控件,例如ListView、AutoCompleteTextView等。
继承RecyclerView.Adapter需要实现以下三个方法:
public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType)
public void onBindViewHolder(ViewHolder holder,int position)
public int getItemCount()
ackage com.recyclerview;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Random;
public class MyRecyclerAdapter extends
RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> {
private final ArrayList<MyBean> sampleData = DemoApp.getSampleData(20);
// 用于创建控件
@Override
public ViewHolder onCreateViewHolder(ViewGroup parentViewGroup, int i) {
/**
* 获得列表项控件(LinearLayer对象)
*
* list_basic_item.xml布局文件中只包含一个<LinearLayer>标签,在该标签中包含了一个<TextView>标签
*
* item是LinearLayout对象
*/
View item = LayoutInflater.from(parentViewGroup.getContext()).inflate(
R.layout.list_basic_item, parentViewGroup, false);
return new ViewHolder(item);
}
// 为控件设置数据
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
// 获取当前item中显示的数据
final MyBean rowData = sampleData.get(position);
// 设置要显示的数据
viewHolder.textViewSample.setText(rowData.getSampleText());
viewHolder.itemView.setTag(rowData);
}
@Override
public int getItemCount() {
return sampleData.size();
}
// 删除指定的Item
public void removeData(int position) {
sampleData.remove(position);
// 通知RecyclerView控件某个Item已经被删除
notifyItemRemoved(position);
}
// 在指定位置添加一个新的Item
public void addItem(int positionToAdd) {
sampleData.add(positionToAdd, new MyBean("lyc " + new Random().nextInt(100)));
// 通知RecyclerView控件插入了某个Item
notifyItemInserted(positionToAdd);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView textViewSample;
public ViewHolder(View itemView) {
super(itemView);
textViewSample = (TextView) itemView
.findViewById(R.id.textViewSample);
}
}
}
最后看一下效果图:
1006

被折叠的 条评论
为什么被折叠?



