今年用了Android Studio后才认识到RecyclerView......略菜.....编写完成后现在去看又感觉不太懂了....所以今天想要总结下,让自己以后回顾的时候可以快一点...
PS:recyclerView网上有很多大神的资料写的很屌,菜如我只取了一瓢
- 先上个效果图吧:
以上的图标请自找。。。
- 列出下程序的目录(黑框框中的都是,其它的请自动忽略)
如上图所示:
MyItemClickListener : 列表行点击事件的接口,实现后用于响应列表点击事件
MyItemLongClickListener:列表行长按事件的接口,实现后用于响应列表长按事件
ContentViewHolder:列表行视图容器,对应的section_item.xml中控件都绑定在此,实现一个容器的显示,也就是列表的一行
FootViewHolder:列表尾视图容器,对应的section_footer.xml中控件都绑定在此,实现一行列表尾的显示
HeadViewHolder:列表头视图容器,对应的section_header.xml中控件都绑定在此,实现一行列表头的显示
MainActivity:实现activity_main.xml中recyclerView的绑定和显示
-
其中:
- 每个ViewHolder对应一个xml(如ContentViewHolder对应section_item)
- 每个ViewHolder都会在MyRecycViewAdapter中初始化,并实现控件的赋值
- 生成列表只需要以下几步:
- 1、在activity_main.xml中创建一个RecyclerView的控件,并在MainAcitivity中绑定
- 2、创建一个MyRecyclerVIewAdapter的对象,并且把你需要显示的数据传递给它
- 3、使用RecyclerView.setAdapter(MyRecyclerVIewAdapter对象)实现列表的显示
- 4、若需要更新,使用MyRecyclerVIewAdapter对象.notifyDataSetChanged()
下面就附上代码
MyItemClickListener 列表行点击事件接口
public interface MyItemClickListener {
public void MyItemClick(View view, int position);
}
MyItemLongClickListener 列表行长按事件接口
public interface MyItemLongClickListener {
public void MyItemLongClick(View view, int position);、
}
ContentViewHolder 继承自RecyclerView.ViewHolder,section_item.xml中的控件都绑定于此,我们可以通过ContentViewHolder对象来获取其中的控件,进而赋值(如:ContentViewHolder对象.tv.setText( "xxxx");)
public class ContentViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
//xml中的控件,由于要在会在MyRecyclerViewAdapter中调用,所以不能为私有
TextView tv;
View cutLine;
ImageView icon;
//点击事件和长按事件
private MyItemClickListener mItemClickListener;
private MyItemLongClickListener mItemLongClickListener;
//这个是ContentViewHolder的构造函数,会在MyRecyclerViewAdapter中调用,生成ContentViewHolder一个对象
public ContentViewHolder(View itemView,MyItemClickListener mItemClickListener,MyItemLongClickListener mItemLongClickListener) {
super(itemView);
tv = (TextView)itemView.findViewById(R.id.tv);
cutLine = (View)itemView.findViewById(R.id.cutLine);
icon = (ImageView)itemView.findViewById(R.id.icon);
this.mItemClickListener = mItemClickListener;
this.mItemLongClickListener = mItemLongClickListener;
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
//短按
@Override
public void onClick(View v) {
if(mItemClickListener != null){
mItemClickListener.MyItemClick(v,getPosition()); //若不为空则调用MyItemClickListener的MyItemClick方法
}
}
//长按
@Override
public boolean onLongClick(View v) {
if(mItemLongClickListener != null){
mItemLongClickListener.MyItemLongClick(v,getPosition()); //若不为空则调用MyItemLongClickListener的MyItemLongClick方法
}
return true;
}
}
section_item.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"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/column"
android:layout_width="match_parent"
android:layout_height="50dp">
<ImageView
android:id="@+id/icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
/>
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_toRightOf="@+id/icon"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:text="mxy"
android:gravity="center_vertical"
/>
</RelativeLayout>
<View
android:id="@+id/cutLine"
android:layout_width="match_parent"
android:layout_height="0.3dp"
android:background="@color/black"/>
</LinearLayout>
FootViewHolder 列表尾viewholder,列表尾也可以像ContentViewHolder一样放入很多控件,我只放了一个TextView
public class FootViewHolder extends RecyclerView.ViewHolder {
TextView footer_tv;
public FootViewHolder(View itemView) {
super(itemView);
footer_tv = (TextView)itemView.findViewById(R.id.footer_tv);
}
}
section_footer.xml 列表尾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/footer_tv"
android:layout_width="match_parent"
android:layout_height="20dp"
android:text="footer_tv"
android:gravity="center"
android:background="#30696969"
/>
</LinearLayout>
HeadViewHolder列表头viewholder
public class HeadViewHolder extends RecyclerView.ViewHolder {
TextView header_tv;
public HeadViewHolder(View itemView) {
super(itemView);
header_tv = (TextView)itemView.findViewById(R.id.header_tv);
}
}
section_header.xml 列表头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/header_tv"
android:layout_width="match_parent"
android:layout_height="20dp"
android:text="header_tv"
android:gravity="center"
android:background="#30696969"
/>
</LinearLayout>
MyRecyclerViewAdapter 这个是核心,看上去很长,但其实层次感很强,主要分为以下4部分
- 1 ViewHolder的Create
- 2 ViewHolder的赋值
- 3 列表的行数
- 4 其他部分
- 4.1 因为我有三个ViewHolder分别表示content,head,foot所以我需要在getItemViewType中判断
- 4.2 因为我有点击事件,所以需要点击方法
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 0; //表格头
private static final int TYPE_CONTENT = 1; //表格内容
private static final int TYPE_FOOTER = 2; //表格尾
private LayoutInflater inflater;
private List<String> slist; //标识,标识是头还是尾,还是内容
private List<contentData> cList; //头或尾或内容的数据
MyItemClickListener mItemClickListener;
MyItemLongClickListener mItemLongClickListener;
public MyRecyclerViewAdapter(Context context,List<allData> list){
this.slist = list.get(0).getSlist();
this.cList =list.get(0).getMlist();
inflater=LayoutInflater. from(context);
}
/************************************此处区分viewholder类型***************************************/
//这里判断viewType类型,到底是header还是footer还是content
@Override
public int getItemViewType(int postion){
if(slist.get(postion).equals("head")){return TYPE_HEADER;}
else if (slist.get(postion).equals("foot")){return TYPE_FOOTER;}
else{return TYPE_CONTENT;}
// if(postion == 0){return TYPE_HEADER;} //header
// else if(postion == getItemCount()-1){return TYPE_FOOTER;} //footer
// else{return TYPE_CONTENT;} //content
}
/************************************点击事件的方法***************************************/
//表格行点击方法
public void setOnItemClickListener(MyItemClickListener listener){
this.mItemClickListener = listener;
}
//表格行长按方法
public void setOnItemLongClickListener(MyItemLongClickListener listener){
//listener为MainAcitivity传递进来的listener
this.mItemLongClickListener = listener;
}
/************************************create部分***************************************/
//此函数中根据xml生成View对象,并传递进入对应的ViewHolder构造函数,生成对应的Viewholder对象,并返回
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == TYPE_CONTENT){ //表格内容
View view = inflater.inflate(R.layout.section_item,parent, false); //根据xml生成View对象
ContentViewHolder viewholder = new ContentViewHolder(view,mItemClickListener,mItemLongClickListener);
return viewholder;
}else if(viewType == TYPE_HEADER){//表格头
View view = inflater.inflate(R.layout.section_header,parent, false);
HeadViewHolder headholder = new HeadViewHolder(view);
return headholder;
}else{//表格尾
View view = inflater.inflate(R.layout.section_footer,parent, false);
FootViewHolder footholder = new FootViewHolder(view);
return footholder;
}
}
/************************************为ViewHolder中的控件赋值部分***************************************/
//此函数中holder即为onCreateViewHolder返回的的holder,根据这些holder获取对应的控件,进行赋值
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if(holder instanceof ContentViewHolder){ // content 表格内容
ContentViewHolder contentholder = (ContentViewHolder) holder;
contentholder.tv.setText(cList.get(position).getDescrib());
contentholder.icon.setImageResource(cList.get(position).getIconID());
}else if(holder instanceof HeadViewHolder){ //header 表格头
HeadViewHolder headholder = (HeadViewHolder) holder;
headholder.header_tv.setText(cList.get(position).getDescrib());
}else{ //footer 表格尾
FootViewHolder footholder = (FootViewHolder) holder;
footholder.footer_tv.setText(cList.get(position).getDescrib());
}
}
/************************************列表行数***************************************/
//此处返回表格的行数,也就是数据的size
@Override
public int getItemCount() {
return slist.size();
}
}
MainAcitvity主要分为数据的生成,和设置recyclerView的适配
public class MainActivity extends AppCompatActivity implements MyItemClickListener, MyItemLongClickListener {
private RecyclerView recyclerView;
private MyRecyclerViewAdapter recycleAdapter;
private List<String> slist =new ArrayList<String>();
private List<contentData> clist = new ArrayList<contentData>();
private List<allData> mylist = new ArrayList<allData>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
recyclerView = (RecyclerView)this.findViewById(R.id.recyclerView);
recycleAdapter = new MyRecyclerViewAdapter(this,mylist);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
//设置为垂直布局,这也是默认的
layoutManager.setOrientation(OrientationHelper.VERTICAL);
//设置布局管理器
recyclerView.setLayoutManager(layoutManager);
//设置Adapter
recyclerView.setAdapter(recycleAdapter);
//设置增加或删除条目的动画
recyclerView.setItemAnimator(new DefaultItemAnimator());
//分割线
// recyclerView.addItemDecoration(new RecyclerDivideLine(Main.this,LinearLayoutManager.VERTICAL));
// recycleAdapter.setOnItemClickListener(this);
// recycleAdapter.setOnItemLongClickListener(this);
recycleAdapter.setOnItemClickListener(this);
recycleAdapter.setOnItemLongClickListener(this);
}
//数据初始化,其中在slist中add的是标识符,head就说明这行是表格头,body说明这行是表格内容,
//而clist中add的有两个一个是图片的ID,一个是文字的说明,而head和foot没有图片ID
private void initData(){
clist.add(new contentData(1,"this is head1"));slist.add("head");
clist.add(new contentData(R.drawable.ins,"仪表说明"));slist.add("body");
clist.add(new contentData(R.drawable.handle,"操作说明"));slist.add("body");
clist.add(new contentData(1,"this is head2"));slist.add("head");
clist.add(new contentData(R.drawable.vision,"版本说明"));slist.add("body");
clist.add(new contentData(R.drawable.err,"报错指南"));slist.add("body");
// clist.add(new contentData(5,"footer1"));slist.add("foot");
clist.add(new contentData(1,"this is head3"));slist.add("head");
clist.add(new contentData(R.drawable.buy,"业务咨询"));slist.add("body");
clist.add(new contentData(R.drawable.fix,"售后返修"));slist.add("body");
clist.add(new contentData(1,"this is head4"));slist.add("head");
clist.add(new contentData(R.drawable.sms,"短信发送"));slist.add("body");
clist.add(new contentData(5,"this is foot1"));slist.add("foot");
mylist.add(new allData(clist,slist));
}
//列表行的点击在此响应
@Override
public void MyItemClick(View view, int position) {
Toast.makeText(this, ""+position, Toast.LENGTH_SHORT).show();
}
//列表行的长按在此响应
@Override
public void MyItemLongClick(View view, int position) {
Toast.makeText(this, ""+position, Toast.LENGTH_SHORT).show();
}
}
acitivity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.myapplication.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
contentData包括两个参数,一个是icon也就是图标的ID,一个是describe也就是文字说明
public class contentData {
public int getIconID() {
return iconID;
}
public void setIconID(int iconID) {
this.iconID = iconID;
}
private int iconID;
public String getDescrib() {
return describ;
}
public void setDescrib(String describ) {
this.describ = describ;
}
private String describ;
public contentData(int iconID,String describ){
this.iconID = iconID;
this.describ =describ;
}
}
allData 其中mlist为内容数据模型,slist为描述数据模型
public class allData {
private List<contentData> mlist;
private List<String> slist;
public allData(List<contentData> mlist,List<String> slist){
this.mlist = mlist;
this.slist = slist;
}
public List<String> getSlist() {
return slist;
}
public void setSlist(List<String> slist) {
this.slist = slist;
}
public List<contentData> getMlist() {
return mlist;
}
public void setMlist(List<contentData> mlist) {
this.mlist = mlist;
}
}