在初接触Android的时候,如果需要显示一列表的数据,我们刚开始想到的肯定是ListView、GridView,还有甚至ExpandableListView,,但是随着Android的不断发展,需求的不断深入,ListView这类基本控件已经越来越满足不了开发者的要求了,所以,Google在support v7包中,加入一个新的控件——RecyclerView。这个RecyclerView结合了ListView和GridView的优点,并且提供高度自由的扩展性,因此备受推崇。当然,这也导致它使用起来会比ListView麻烦那么一丢丢,这也是我原来一直没使用RecyclerView的原因之一,不过,不断学习新的东西是必须的,所以我还是下定决心搞定它,在这里就记录一下一步一步学习RecyclerView的过程。
首先,我们要介绍一下RecyclerView中几个重要的类,这几个类也可以说是RecyclerView的核心类。
1、RecyclerView.Adapter 适配器,为RecyclerView提供数据。
2、RecyclerView.LayoutManager 布局管理器,为RecyclerView实现不同布局效果。
3、RecyclerView.ItemDecoration item装饰类,为RecyclerView的item添加分割线等。
4、RecyclerView.ItemAnimator item动画类,实现item添加或删除时的动画。
这些类都是抽象类,如果利用不同的实现类,我们就能高度定制RecyclerView。
但是RecycylerView并没有处理点击事件的监听器,所以如果要监听RecycylerView的点击事件,我们需要自己写监听器(所以我之前觉得这玩意很麻烦)。
要使用RecyclerView,由于该控件并不在Andorid SDK中的,而是在support v7包中,因此我们要手动添加该控件。
在build.gradle中添加如下依赖:
//RecyclerView
compile 'com.android.support:recyclerview-v7:25.2.0'
下面说说基本使用:
首先需要写两个简单的布局文件:
MainActivity:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_test"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
item布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="#00CED1"
android:orientation="vertical">
<TextView
android:id="@+id/tv_test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#000000"
android:textSize="24sp" />
</LinearLayout>
这两个布局都非常简单,MainActivity中就一个RecycylerView,item布局中也只有一个TextView。
RecyclerView的适配器,继承自RecyclerView.Adapter,下面再讲它的几个方法。
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyViewHolder> {
private List<String> stringList;
public TestAdapter(List<String> stringList) {
this.stringList = stringList;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_test_recyclerview, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
holder.tvTest.setText(stringList.get(position));
}
@Override
public int getItemCount() {
return stringList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
public TextView tvTest;
public MyViewHolder(View itemView) {
super(itemView);
tvTest = (TextView) itemView.findViewById(R.id.tv_test);
}
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView rvTest = (RecyclerView) findViewById(R.id.rv_test);
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
// GridLayoutManager mGridLayoutManager = new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false);
// StaggeredGridLayoutManager mStaggeredGridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
TestAdapter mTestAdapter = new TestAdapter(getList());
rvTest.setLayoutManager(mLinearLayoutManager);
rvTest.setAdapter(mTestAdapter);
}
private List<String> getList() {
List<String> stringList = new ArrayList<>();
for (int i = 0; i < 100; i++) {
String string = "Item " + i;
stringList.add(string);
}
return stringList;
}
}
MainActivity中这两行已经被注释掉了,下面再解释它们是干什么的。
// GridLayoutManager mGridLayoutManager = new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false);
// StaggeredGridLayoutManager mStaggeredGridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
经过上面的操作,我们已经可以成功使用RecycylerView显示数据了,如果不出现失误的话,应该会出现下面的结果:
效果看起来跟ListView差不多,但是操作可能还要繁琐那么一丢丢,而且也并没有发现什么特别的地方,不要着急,这是基本使用,下面先说说适配器中的几个抽象方法:
public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
public abstract void onBindViewHolder(VH holder, int position);
public abstract int getItemCount();
onCreateViewHolder();该方法会在RecyclerView需要展示一个item的时候回调,重写该方法,使ViewHolder加载item的布局,布局复用,提高性能,就ListView的优化一样,只不过RecyclerView把这个集成到官方方法中了。
onBindViewHolder();该方法是填充绑定item数据的。
getItemCount();该方法是返回item的数量。
总的来说,RecyclerView的Adapter和ListView的Adatper用法还是差不多的。
下面解释一下注释掉的那两行是什么意思。
刚才使用的LinearLayoutManager是线性布局管理器,也就是跟线性布局差不多,可以让item呈垂直或者水平排列。
LinearLayoutManager有两种构造方法:
public LinearLayoutManager(Context context) ;
public LinearLayoutManager(Context context, int orientation, boolean reverseLayout);
第一个参数是Context不必多说,第二个参数orientation是布局方向,其值有LinearLayoutManager.HORIZONTAL(水平方向)和LinearLayoutManager.VERTICAL(垂直方向),第三个参数reverseLayout是是否逆向布局,如果为true,则为逆向布局,举个例子,如果是水平布局,然后设置第三个参数为true,那么RecycylerView将是从右向左滑动,具体效果大家可以试一下。
除了LinearLayoutManager,官方还提供了另外两种布局管理器,GridLayoutManager和StaggeredGridLayoutManager,也就是刚才我注释掉的两行。
GridLayoutManager是表格布局管理器,也就跟表格布局差不多,使用它的效果跟GridView的效果差不多,如果注释掉LinearLayoutManager那一行,再打开GridLayoutManager,设置mGridLayoutManager。
// LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
GridLayoutManager mGridLayoutManager = new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false);
// StaggeredGridLayoutManager mStaggeredGridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
TestAdapter mTestAdapter = new TestAdapter(getList());
rvTest.setLayoutManager(mGridLayoutManager);
重新运行程序的话,应该会出现下面的结果:
GridLayoutManager也有两种构造方法:
public GridLayoutManager(Context context, int spanCount);
public GridLayoutManager(Context context, int spanCount, int orientation,boolean reverseLayout);
第一个参数是上下文,第二个参数spanCount是行数或列数,第三个orientation是布局方向,第四个参数reverseLayout是是否逆向布局,跟LinearLayoutManager差不多,这里不过多解释。
StaggeredGridLayoutManager是瀑布流布局管理器,瀑布流效果相信大家现在经常看到,如果只使用LIstView或者GridView的话,实现起来是很麻烦的,但是使用RecycylerView就会简单很多,只要使用这个瀑布流布局管理器就行了,如果注释掉LinearLayoutManager那一行,再打开GridLayoutManager,设置mGridLayoutManager。
// LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
// GridLayoutManager mGridLayoutManager = new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false);
StaggeredGridLayoutManager mStaggeredGridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
TestAdapter mTestAdapter = new TestAdapter(getList());
rvTest.setLayoutManager(mStaggeredGridLayoutManager);
重新运行程序的话,应该会出现下面的结果:
单纯使用StaggeredGridLayoutManager效果也跟GridLayoutManager差不多,没有出现瀑布流效果,所以还需要修改每一个item的height(如果是横向布局的话,则修改width),我们需要将Adapter中的OnBindViewHolder()方法修改一下。
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.tvTest.setText(stringList.get(position));
ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
lp.height = (int) (100 + Math.random() * 300);
holder.itemView.setLayoutParams(lp);
}
添加几行代码,即随机设置item的height。
再次运行程序,应该会出现下面的结果:
StaggeredGridLayoutManager只有一种构造方法:
public StaggeredGridLayoutManager(int spanCount, int orientation);
第一个参数spanCount是行数或列数,第二个参数orientation是布局方向。
这篇文章主要记录了RecycylerView的基本使用,如何添加数据并显示出来,并且记录的RecycylerView三种布局管理器的基本效果。由此可见,一个控件能显示出几种不同效果,确实比一个单纯的ListView或者GridView要强大得多,这只是冰山一角,RecycylerView的高度自由性是众人所颂的,要想随心所欲的使用RecycylerView,我们先要了解它的基本使用,下次再记录一下RecycylerView是如何处理点击事件的。