Android RecyclerView 二级列表实现

前段时间项目提了个新需求:我的红包需要做成二级列表的形式,实现的效果如下图所示:

支持的功能:

1.可自定义item的样式

2.自定义折叠效果

3.自定义展开方式

下面我说一下我在demo中的使用方式

1.demo中的数据来源于这样格式的json,所以你可以让后端给你返回包含这样格式的json

2.MainActivity的布局activity_main.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="view.lyd.com.sectionrecyclerviewdemo.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

3.适配器HotelEntityAdapter:

package adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import java.util.ArrayList;

import entity.HotelEntity;
import utils.HotelUtils;
import view.lyd.com.sectionrecyclerviewdemo.R;

/**
 * Created by yushuangping on 2018/8/23.
 */

public class HotelEntityAdapter extends SectionedRecyclerViewAdapter<HeaderHolder, DescHolder, RecyclerView.ViewHolder> {


    public ArrayList<HotelEntity.TagsEntity> allTagList;
    private Context mContext;
    private LayoutInflater mInflater;

    private SparseBooleanArray mBooleanMap;//记录下哪个section是被打开的

    public HotelEntityAdapter(Context context) {
        mContext = context;
        mInflater = LayoutInflater.from(context);
        mBooleanMap = new SparseBooleanArray();
    }

    public void setData(ArrayList<HotelEntity.TagsEntity> allTagList) {
        this.allTagList = allTagList;
        mBooleanMap.put(0, true);
        notifyDataSetChanged();
    }

    /**
     * 一共有多少个section需要展示, 返回值是我们最外称list的大小,在我们的示例图中,
     * 对应的为热门品牌—商业区—热门景点 等,对应的数据是我们的allTagList
     *
     * @Override
     */

    protected int getSectionCount() {
        return HotelUtils.isEmpty(allTagList) ? 0 : allTagList.size();
    }

    /**
     * 来展示content内容区域,返回值是我们需要展示多少内容,在本例中,我们超过8条数据只展示8条,
     * 点击展开后就会展示全部数据,逻辑就在这里控制。 对应数据结构为tagInfoList
     *
     * @param section
     * @return
     */
    @Override
    protected int getItemCountForSection(int section) {
        int  count = allTagList.get(section).tagInfoList.size();
        if (count >= 1 && !mBooleanMap.get(section)) {
            count = 0;
        }
        if (section==0&&mBooleanMap.get(section)){
            count = allTagList.get(section).tagInfoList.size();
        }
        return HotelUtils.isEmpty(allTagList.get(section).tagInfoList) ? 0 : count;
    }

    //是否有footer布局

    /**
     * 判断是否需要底部footer布局,在该例中,我们并不需要显示footer,所以默认返回false就可以,
     * 如果你对应的section需要展示footer布局,那么就在对应的section返回true就行了
     *
     * @param section
     * @return
     */
    @Override
    protected boolean hasFooterInSection(int section) {
        return false;
    }

    @Override
    protected HeaderHolder onCreateSectionHeaderViewHolder(ViewGroup parent, int viewType) {
        return new HeaderHolder(mInflater.inflate(R.layout.hotel_title_item, parent, false));
    }


    @Override
    protected RecyclerView.ViewHolder onCreateSectionFooterViewHolder(ViewGroup parent, int viewType) {
        return null;
    }

    @Override
    protected DescHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
        return new DescHolder(mInflater.inflate(R.layout.hotel_desc_item, parent, false));
    }


    @Override
    protected void onBindSectionHeaderViewHolder(final HeaderHolder holder, final int section) {
        holder.openView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean isOpen = mBooleanMap.get(section);
//                String text = isOpen ? "展开" : "关闭";
                mBooleanMap.put(section, !isOpen);
//                holder.openView.setText(text);
                notifyDataSetChanged();
            }
        });
        holder.titleView.setText(allTagList.get(section).tagsName);
//        holder.openView.setText(mBooleanMap.get(section) ? "关闭" : "展开");//true显示关闭字段,false显示展开字段
        holder.openView.setBackgroundResource(mBooleanMap.get(section) ? R.mipmap.arrow_up : R.mipmap.arrow_down);

    }


    @Override
    protected void onBindSectionFooterViewHolder(RecyclerView.ViewHolder holder, int section) {

    }

    /**
     * 这里有一个section和position ,有些人可能会弄混
     * section是区域,也就是我们最外层的index,position是每个section对应的内容数据的position
     *
     * @param holder
     * @param section
     * @param position
     */
    @Override
    protected void onBindItemViewHolder(DescHolder holder, final int section, final int position) {
        holder.descView.setText(allTagList.get(section).tagInfoList.get(position).tagName);
        Log.e("=====AAA===", "section=" + section + ",position=" + position);
        holder.descView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onItemClickListener.onItemClick(section, position);

            }
        });

    }

    private OnItemClickListener onItemClickListener;

    public void setOnItemClick(OnItemClickListener listener) {
        this.onItemClickListener = listener;
    }

    public interface OnItemClickListener {
        void onItemClick(int section, int position);
    }
}

4.在MainActivity中进行调用:

package view.lyd.com.sectionrecyclerviewdemo;

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.widget.Toast;

import adapter.HotelEntityAdapter;
import adapter.SectionedSpanSizeLookup;
import entity.HotelEntity;
import utils.JsonUtils;
/**
 * Created by yushuangping on 2018/8/23.
 */
public class MainActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;
    private HotelEntityAdapter mAdapter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        mAdapter = new HotelEntityAdapter(this);
//        GridLayoutManager manager = new GridLayoutManager(this,4);
        LinearLayoutManager layoutManager=new LinearLayoutManager(this);
        //设置header
//        manager.setSpanSizeLookup(new SectionedSpanSizeLookup(mAdapter,manager));
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setAdapter(mAdapter);
        HotelEntity entity = JsonUtils.analysisJsonFile(this,"json");
        mAdapter.setData(entity.allTagsList);
        mAdapter.setOnItemClick(new HotelEntityAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(int section, int position) {
                Toast.makeText(MainActivity.this,section+"=="+position,Toast.LENGTH_SHORT).show();

            }
        });
    }
}

5.最后demo运行在手机上的效果图如下:

未展开时的效果:

展开时的效果:

如果大家想看具体的实现方式可以下载源码

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值