您的位置:首页 > 其它

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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐