当前位置 博文首页 > 启舰:自定义控件三部曲视图篇(四)——RecyclerView系列之一简
绝望的时候不要那么绝望,高兴的时候不要那么高兴,是你慢慢会学会的。 ——董卿
系列文章: Android自定义控件三部曲文章索引: http://blog.csdn.net/harvic880925/article/details/50995268
转了一年多,又回来继续做Android。果然还是看到代码最让我兴奋……但有些事,没经历过,总归还是遗憾的。在VIVO的游戏中心,有一个特别炫酷的功能:
这个功能就是使用RecyclerView来实现的,在本系列中,我们将最终制作出这样的一个效果出来。
工欲善其事必先利其器,RecyclerView存在于support-v7包中,我们需要在新建的gradle工程中导入support-v7包:
compile 'com.android.support:recyclerview-v7:21.0.3'
gralde 版本较高的同学,会发现compile关键字这里会报警告,在高版本gradle中compile已经弃用了,改成了implementation,所以你可以改为:
implementation 'com.android.support:recyclerview-v7:21.0.3'
加上上面的依赖代码以后,会发现根本不好使,依赖库根本拉不下来。这是为什么呢?
support-v7包并不是通过maven从远程下载的,而是通过Android Studio的SDK Manager来下载到本地,然后再引用的。本地有没有support-v7包,大家可以看下SDK的这个位置(Sdk\extras\android\m2repository\com\android\support):
从这里可以看到,在我的com/android/support目录下有所有的support包,这里也有recyclerview-v7包。如果在该文件夹下,你没有的话,可以通过SDK Manager引入:
下载完成后,在这个文件夹下就会有对应的包存在了,当我们点进去recyclerview-v7文件夹里面,可以看到各种版本:
大家就可以选择这里已有的版本引入了,比如我这里是有25.3.1的,所以我这里最终的引用包是:
implementation 'com.android.support:recyclerview-v7:25.3.1'
在引入support包时,需要有两个注意事项:
implementation 'com.android.support:appcompat-v7:25.3.1'
implementation 'com.android.support:recyclerview-v7:25.3.1'
在这部分,我们首先做出一个最简单的例子,来看下RecyclerView的使用方法。本小节所实现的效果如下图所示:
首先,在XML中引入RecyclerView:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
tools:context=".LinearActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/linear_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
与listView一样,同样需要一个Adapter来将数据和Item视图绑定起来,但不同的的是RecyclerView的Adapter需要派生自RecyclerView.Adapter<RecyclerView.ViewHolder>
当我们写一个Adapter的类派生自RecyclerView.Adapter<RecyclerView.ViewHolder>时,最简单的形式是这样的:
public class RecyclerAdapter extends RecyclerView.Adapter<ViewHolder> {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
}
这三个函数是强制必须重写的,其中:
可见,这三项其实在listview中也都是需要做的,只是这里单独通过回调给列出来了,我们只需要补充上这三个函数,就算实现了Adapter了.
在填充RecyclerAdapter之前,我们知道,一般而言ListView的数据都是从外部传进来的,所以我们需要给RecyclerAdapter添加上一个构造函数,将数据从外部传进来:
private Context mContext;
private ArrayList<String> mDatas;
public RecyclerAdapter(Context context, ArrayList<String> datas) {
mContext = context;
mDatas = datas;
}
为了方便起来,我们传进来的数据非常简单,就是一个String字符串,同时,由于在RecyclerAdater中,经常会用到Context,所以我们也把Context传进来,并且保存起来.
接下来,我们就是先创建一个HolderView,然后填充那三个函数。我们都知道HolderView主要是为了保存每一个Item的视图的控件元素。所以我们要先创建一个Item的xml(item_layout.xml):
<?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">
<TextView
android:id="@+id/item_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp" />
</LinearLayout>
在这个item中,只有一个TextView,所以我们先写一个ViewHolder,ViewHolder的主要作用就是将XML中的控件以变量的形式保存起来,方便我们后面数据绑定.
public class NormalHolder extends RecyclerView.ViewHolder{
public TextView mTV;
public NormalHolder(View itemView) {
super(itemView);
mTV = (TextView) itemView.findViewById(R.id.item_tv);
mTV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext,mTV.getText(),Toast.LENGTH_SHORT).show();
}
});
}
}
在这里,在创建ViewHolder时,将整个ItemView传了进来,然后将TextView从ItemView中取出来保存在mTV变量中.并且,在点击mTV后,弹出这个TextView的内容.
在写好ViewHolder以后,我们就要逐个填充RecyclerAdapter的三个函数了。首先是onCreateViewHolder:
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
return new NormalHolder(inflater.inflate(R.layout.item_layout,parent,false));
}
在每一次需要创建ViewHolder时,都会调用onCreateViewHolder函数,所以我们需要在onCreateViewHolder中返回我们创建的ViewHolder实例。
然后在onBindViewHolder中,将数据与ViewHolder绑定起来:
public void onBindViewHolder(ViewHolder holder, int position) {
NormalHolder normalHolder = (NormalHolder)holder;
normalHolder.mTV.setText(mDatas.get(position));
}
最后,在getItemCount中返回数据的个数:
public int getItemCount() {
return mDatas.size();
}
到这里,整个RecyclerAdapter就实现完了,完整的代码如下,供大家参考:
public class RecyclerAdapter extends RecyclerView.Adapter<ViewHolder> {
private Context mContext;
private ArrayList<String> mDatas;
public RecyclerAdapter(Context context, ArrayList<String> datas) {
mContext = context;
mDatas = datas;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
return new NormalHolder(inflater.inflate(R.layout.item_layout, parent, false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
NormalHolder normalHolder = (NormalHolder) holder;
normalHolder.mTV.setText(mDatas.get(position));
}
@Override
public int getItemCount() {
return mDatas.size();
}
public class NormalHolder extends RecyclerView.ViewHolder {
public TextView mTV;
public NormalHolder(View itemView) {
super(itemView);
mTV = (TextView) itemView.findViewById(R.id.item_tv);
mTV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, mTV.getText(), Toast.LENGTH_SHORT).show();
}
});
}
}
}
之后,回到Activity中,首先,构造一个模拟数据的函数,用于填充RecyclerVIew:
public class LinearActivity extends AppCompatActivity {
…………
private ArrayList<String> mDatas =new ArrayList<>();
private void generateDatas(){
for (int i=0;i<200;i++){
datas.