RecyclerView有标题栏的分类列表 自定义列数(不同行设置不同个子项item)
2018-04-02 17:21
459 查看
上一个的实验室Issue前几天才完成,两个项目都实现了老师要求,算上中途多次放下去做其他issue,这个issue做了差不多有四个月了吧。还好不是改bug,不然四个月时间足够被批评n次了。趁着现在还有印象,把这个issue里最难搞的问题总结一下,之前做的过程也总结了一些遇到的问题,比如后台多个定时器同事运行的问题,settings界面的注意事项等都总结了,这次总结一下花费最多时间去想的问题,中途还经过多次推倒重来,也不是说这个功能多难实现,主要是在几年前的项目上添加新功能,有些吃力,毕竟好多方法都被调用过,不能随意改变,尤其是数据封装好的类型很难去改变,想要找到一个好的方法挺难的,只能找一些折中的方法。这篇博文讲解的是我自己想的一种方法,可能不是最好的,但是适合我的项目,如果有比较好的方法,欢迎一起讨论。
有时候需要对一些数据进行分类显示,还要显示他们的分类标题,普通的GridView是挺难实现的,因为GridView不支持不同行自定义列数,例如我想标题占满一行,其他子项每两个占一行。GridView也可以实现,需要对GridView的方法做大量地重写override,重绘item等等,对一些像我这种菜鸟级别的人来说,门槛太高。后来发现可以使用RecyclerView实现这种功能,RecyclerView支持自定义不同列数。接下来介绍一下如何使用。先看一下做的项目的效果图
解释都写在代码里,直接看代码吧:
先分别新建一个title的layout文件和一个item的layout文件
recyclerview_title.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20sp" android:text="标题"/> </LinearLayout>
recyclerview_item.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/image" android:scaleType="fitXY" android:alpha="0.7" android:src="@drawable/ic_launcher_background"/> <TextView android:id="@+id/item" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:layout_marginTop="40dp" android:gravity="center" android:text="这是一个item" android:textColor="#ffffff" android:textSize="20sp" /> </RelativeLayout>
主界面的layout文件代码:
activity_recycler_view_category_style.xml
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.mrc.csdndemo.RecyclerViewCategory.RecyclerViewCategoryStyle"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:numColumns="auto_fit" android:stretchMode="columnWidth" android:layout_width="fill_parent" android:layout_height="match_parent" android:gravity="center" android:horizontalSpacing="8dp" android:verticalSpacing="8dp"/>/> </LinearLayout> </ScrollView>
新建一个RecyclerView的适配器,代码如下:
RecyclerViewAdapter.java
package com.example.mrc.csdndemo.RecyclerViewCategory; import android.content.Context; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.example.mrc.csdndemo.R; import java.util.List; import java.util.Map; /** * Created by Mr.C on 2018/3/17. */ public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>{ private Context mContext; private LayoutInflater mInflater; private static final int VIEW_TYPE_TITLE= 0; private static final int VIEW_TYPE_ITEM = 1; int IS_TITLE_OR_NOT =1; int MESSAGE = 2; int ColumnNum; List<Map<Integer, String>> mData; public RecyclerViewAdapter(Context context , List<Map<Integer, String>> mData , int ColumnNum) { this.mContext=context; this.ColumnNum=ColumnNum; this.mData= mData; } @Override public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { ViewHolder vh = null; mInflater = LayoutInflater.from(mContext); //判断viewtype类型返回不同Viewholder switch (viewType) { case VIEW_TYPE_TITLE: vh = new HolderOne(mInflater.inflate(R.layout.recyclerview_title, parent, false)); break; case VIEW_TYPE_ITEM: vh = new HolderTwo(mInflater.inflate(R.layout.recyclerview_item, parent,false)); break; } return vh; } @Override public void onBindViewHolder(ViewHolder holder, int position) { if("true".equals(mData.get(position).get(IS_TITLE_OR_NOT))){ holder.mTitle.setText(mData.get(position).get(MESSAGE)); }else { holder.mItem.setText(mData.get(position).get(MESSAGE)); } } //判断RecyclerView的子项样式,返回一个int值表示 @Override public int getItemViewType(int position) { if ("true".equals(mData.get(position).get(IS_TITLE_OR_NOT))) { return VIEW_TYPE_TITLE; } return VIEW_TYPE_ITEM; } //判断是否是title,如果是,title占满一行的所有子项,则是ColumnNum个,如果是item,占满一个子项 @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { //如果是title就占据2个单元格(重点) GridLayoutManager manager = (GridLayoutManager) recyclerView.getLayoutManager(); manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { if("false".equals(mData.get(position).get(IS_TITLE_OR_NOT))){ return 1; }else { return ColumnNum; } } }); } @Override public void onBindViewHolder(ViewHolder holder, int position , List<Object> payloads) { if(payloads.isEmpty()){ onBindViewHolder(holder,position); } else { onBindViewHolder(holder,position); } } //对于不同布局的子项,需要对它进行初始化 @Override public int getItemCount() { return mData.size(); } public class ViewHolder extends RecyclerView.ViewHolder { public TextView mTitle; public TextView mItem; public ImageView mImageView; public ViewHolder(View itemView) { super(itemView); } } public class HolderOne extends ViewHolder { public HolderOne(View viewHolder) { super(viewHolder); mTitle= (TextView) viewHolder.findViewById(R.id.title); } } public class HolderTwo extends ViewHolder{ public HolderTwo(final View viewHolder) { super(viewHolder); mItem =(TextView)viewHolder.findViewById(R.id.item); mImageView =(ImageView) viewHolder.findViewById(R.id.image); } } }
最后就是主界面的Java文件
RecyclerViewCategoryStyle.java
package com.example.mrc.csdndemo.RecyclerViewCategory; import android.graphics.Rect; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; import com.example.mrc.csdndemo.R; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class RecyclerViewCategoryStyle extends AppCompatActivity { RecyclerView mRecyclerView ; LinearLayoutManager mLayoutManager; RecyclerViewAdapter mRecyclerViewAdapter; int IS_TITLE_OR_NOT =1; int MESSAGE = 2; List<Map<Integer, String>> mData =new ArrayList<>(); Map<Integer, String> map = new HashMap<Integer, String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recycler_view_category_style); findView(); init(); mRecyclerViewAdapter = new RecyclerViewAdapter(this, mData, 2); mRecyclerView.setAdapter(mRecyclerViewAdapter); } void findView(){ mRecyclerView =(RecyclerView)findViewById(R.id.recyclerView); //2表示列数为2,LinearLayoutManager.VERTICAL表示竖直布局 mLayoutManager = new GridLayoutManager(this, 2, LinearLayoutManager.VERTICAL, false); mRecyclerView.addItemDecoration(new SpaceItemDecoration(12));//item之间的间距 mRecyclerView.setLayoutManager(mLayoutManager); } void init(){ //对item的数据进行初始化 for(int i=0;i<15 ;i++){ map = new HashMap<Integer, String>(); map.put(IS_TITLE_OR_NOT , "false"); map.put(MESSAGE , "item "+(i+1)); mData.add(map); } //对分类标题进行初始化 map = new HashMap<Integer, String>(); map.put(IS_TITLE_OR_NOT , "true"); map.put(MESSAGE , "1-3的分类标题"); mData.add(0,map); map = new HashMap<Integer, String>(); map.put(IS_TITLE_OR_NOT , "true"); map.put(MESSAGE , "4-7的分类标题"); mData.add( 4,map); map = new HashMap<Integer, String>(); map.put(IS_TITLE_OR_NOT , "true"); map.put(MESSAGE , "8-15的分类标题"); mData.add(9,map); for (int i=0;i<mData.size();i++){ Log.d("Title",mData.get(i).get(IS_TITLE_OR_NOT)); Log.d("Title_message",mData.get(i).get(MESSAGE)); } } //设置recyclerView中item的上下左右间距 public class SpaceItemDecoration extends RecyclerView.ItemDecoration { private int space; public SpaceItemDecoration(int space) { this.space = space; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { //分别设置item的间距 if (parent.getChildViewHolder(view).getItemViewType() == 0) { outRect.bottom = 0; outRect.top = space / 2; } else { outRect.bottom = space; outRect.top = space; } outRect.right = space; outRect.left = space; } } }
这是我写的Demo的效果图:
代码已经打包放在里面,看不懂的伙伴可以去下载下来研究研究:
RecyclerView有标题栏的分类列表 自定义列数(不同行设置不同个子项item)
相关文章推荐
- Android客户端之“微服私访”App的系统学习(七)XRecyclerView快速实现列表界面+自定义Search输入框,软键盘搜索按钮监听+TextView部分样式改变
- Android横竖屏切换View设置不同尺寸或等比例缩放的自定义View的onMeasure解决方案(2)
- Android实现RecyclerView自定义列表,SwipeRefreshLayout实现下拉刷新
- 【Android 仿微信通讯录 导航分组列表-下】自定义View为RecyclerView打造右侧索引导航栏IndexBar
- Android实现RecyclerView自定义列表、点击事件以及下拉刷新
- Android 动态设置列表样式,不用ListView或者RecyclerView
- RecyclerView--GridLayoutManager设置某个item占据的列数
- 列表标题栏添加CheckBox(自定义HanderView的时候实现)
- 为RecyclerView的不同item项实现不同的布局(添加分类Header)
- RecyclerView--GridLayoutManager设置某个item占据的列数
- Android实现RecyclerView自定义列表、点击事件以及下拉刷新
- Android RecyclerView中实现自定义GridView的方式(实现不同item)
- android中RecyclerView使用自定义的列表布局
- Android RecyclerView(八)设置自定义 下拉刷新 与 上拉加载数据
- 自定义可以设置EmptyView的RecyclerView
- RecyclerView条目跳转+SpringView数据刷新加载+MVP+OKhttp+拦截器+自定义view 实现请求网络数据的二级列表购物车
- 获取自定义标题栏组件要设置setContentView
- 【笔记】Android使用RecyclerView实现可自定义节点的树形列表
- iOS 设置一行颜色不同的NSString 、剪切图片、设置TableView的自定义header
- 创建产品列表控件时触发自定义DataUpated事件时,设置MultiView.ActiveViewIndex无效