RecyclerView组件自定义分组

轻松实现类试与 header footer item等分组的Adapter组件。好用方便。

原理: 将每一个Item 从position 转化为section(段) row(列)数据格式,方便定位具体属于那一组的哪一个Item的数据。数据格式如下:

 public static class IndexPath{
        public int row;
        public int section;

        @Override
        public String toString() {
            return "IndexPath [row=" + row + ", section=" + section + "]";
        }
    }

关键点一:
count的计算法,count 从以前的position现在复杂化了,应该包含每一段的header、item、 footer的总和,算法较复杂,这里讲定义为final不让重复写。

  @Override
    final public int getItemCount() {
        int section = getSection();
        int count = 0;
        for (int i = 0; i < section; i++) {
            int header = isGroupHeaderForSection(i)?1:0;
            int footer = isGroupFooterForSection(i)?1:0;
            count = count + getRow(i) + header + footer;
        }
        return count;
    }

关键2:
header 和 footer的动态处理,动态的删减


  /**
     * 该组是否包含HeadView
     * @param section
     * @return
     */
    public boolean isGroupHeaderForSection(int section){
        return false;
    }
    /**
     * 该组是否包含FooterVew
     * @param section
     * @return
     */
    public boolean isGroupFooterForSection(int section){
        return false;
    }

关键3:
将position转化为indexpath的算法

    /**
     * 根据 postion 计算 indexPath
     * @param position
     * @return
     */
    final public IndexPath findIndexPathForPosition(int position){
        position -= getListHeadCount();
        int section = getSection();
        int count = 0;
        int sec = 0;
        for (int i = 0; i < section; i++) {
            int header = isGroupHeaderForSection(i)?1:0;
            int footer = isGroupFooterForSection(i)?1:0;

            count = count + getRow(i) + header + footer;
            if (count > position) {
                sec = i;
                count = count - getRow(i) - header - footer;
                break;
            }
        }

        IndexPath indexPath = new IndexPath();
        indexPath.section = sec;
        indexPath.row = position-count;

        Log.d("demo", "" +indexPath +" po: "+ position +" getRow:"+getRow(indexPath.section));

        return indexPath;
    }

完成上面的情况,就可以进行封装了:
全码:

package com.hujiang.designsupportlibrarydemo.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
 * Created by tp on 2016/11/16.
 */
public abstract class BaseRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {



    public Context mContext;



    public int getSection(){//获取切片
        return 1;
    }

    /**
     * 根据切片section 获取对应的 row item
     * @param section
     * @return
     */
    public abstract int getRow(int section);

    @Override
    final public int getItemCount() {
        int section = getSection();
        int count = 0;
        for (int i = 0; i < section; i++) {
            int header = isGroupHeaderForSection(i)?1:0;
            int footer = isGroupFooterForSection(i)?1:0;
            count = count + getRow(i) + header + footer;
        }
        return count;
    }


    @Override
    final public int getItemViewType(int position) {
        IndexPath indexPath = findIndexPathForPosition(position);
        if (isGroupHeaderForSection(indexPath.section) && indexPath.row == 0 ) {//有头
            return getItemHeaderViewType(indexPath);
        }

        if (isGroupFooterForSection(indexPath.section)) {//有尾
            int row = getRow(indexPath.section);
            int header = isGroupHeaderForSection(indexPath.section)?1:0;
            if (row == indexPath.row - header) {//到尾部了
                return getItemFooterViewType(indexPath);
            }
        }
        return getItemViewType(indexPath);
    }

    /**
     *
     * @param indexPath 改位置的 view type
     * @return
     */
    public int getItemViewType(IndexPath indexPath){
        return 0;
    }

    /**
     *
     * @param indexPath section Footer 位置的 view type
     * @return
     */
    public int getItemFooterViewType(IndexPath indexPath){
        return 1;
    }
    /**
     *
     * @param indexPath  section Header position view type
     * @return
     */
    public int getItemHeaderViewType(IndexPath indexPath){
        return 2;
    }


    /**
     * 根据 postion 计算 indexPath
     * @param position
     * @return
     */
    final public IndexPath findIndexPathForPosition(int position){
        position -= getListHeadCount();
        int section = getSection();
        int count = 0;
        int sec = 0;
        for (int i = 0; i < section; i++) {
            int header = isGroupHeaderForSection(i)?1:0;
            int footer = isGroupFooterForSection(i)?1:0;

            count = count + getRow(i) + header + footer;
            if (count > position) {
                sec = i;
                count = count - getRow(i) - header - footer;
                break;
            }
        }

        IndexPath indexPath = new IndexPath();
        indexPath.section = sec;
        indexPath.row = position-count;

        Log.d("demo", "" +indexPath +" po: "+ position +" getRow:"+getRow(indexPath.section));

        return indexPath;
    }

    /**
     * listview  header 的数量决定 position 的位置
     * @return
     */
    public int getListHeadCount(){
        return 0;
    }


    @Override
    final public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        IndexPath indexPath = findIndexPathForPosition(position);

        int header = isGroupHeaderForSection(indexPath.section)?1:0;

        if (isGroupHeaderForSection(indexPath.section) && indexPath.row == 0) {//有头
            onBindHeaderViewHolder(holder,position,indexPath);
            return;
        }

        if (isGroupFooterForSection(indexPath.section)) {//有尾
            int row = getRow(indexPath.section);
            if (row == indexPath.row - header) {//到尾部了
                onBindFooterViewHolder(holder,position,indexPath);
                return;
            }
        }

        if (isGroupHeaderForSection(indexPath.section)) {//包含header row位置 -1 和 list index 保持一致
            indexPath.row -= 1;
        }

        onBindItemViewHolder(holder,position,indexPath);
    }


    public  void onBindHeaderViewHolder(RecyclerView.ViewHolder holder, int position,IndexPath indexPath){}
    public  void onBindFooterViewHolder(RecyclerView.ViewHolder holder, int position,IndexPath indexPath){}
    public abstract void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position,IndexPath indexPath);

    /**
     * 该组是否包含HeadView
     * @param section
     * @return
     */
    public boolean isGroupHeaderForSection(int section){
        return false;
    }
    /**
     * 该组是否包含FooterVew
     * @param section
     * @return
     */
    public boolean isGroupFooterForSection(int section){
        return false;
    }




    public View getHeaderView(int position,int section,View convertView,ViewGroup parent){
        if (isGroupHeaderForSection(section)) {
            TextView header = null;
            if (convertView!=null) {
                header =(TextView) convertView;
            }else {
                header = new TextView(mContext);
            }
            header.setText("第:"+section+" header");
            return header;
        }
        return null;
    }
    public View getFooterView(int position,int section,View convertView,ViewGroup parent){
        if (isGroupFooterForSection(section)) {
            TextView footer =null;
            if (convertView != null) {
                footer = (TextView) convertView;
            }else {
                footer = new TextView(mContext);
            }
            footer.setText("第:"+section +" footer");
            return footer;
        }
        return null;
    }


    public static class IndexPath{
        public int row;
        public int section;

        @Override
        public String toString() {
            return "IndexPath [row=" + row + ", section=" + section + "]";
        }
    }


}

使用方法:
继承基类adapter 例如:

package com.hujiang.designsupportlibrarydemo.adapter;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.hujiang.designsupportlibrarydemo.R;

import java.util.List;

/**
 * Created by tp on 2016/11/16.
 */

public class RecylerGroupAdapter extends BaseRecyclerAdapter {



    private List<String> list;

    public RecylerGroupAdapter(List<String> list) {
        this.list = list;
    }

    @Override
    public int getRow(int section) {
        return  section;
        //return 1;
    }

    @Override
    public int getSection() {
        return  list.size();
    }

    @Override
    public boolean isGroupFooterForSection(int section) {
        return true;
    }

    @Override
    public boolean isGroupHeaderForSection(int section) {
        return  true;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        View view = layoutInflater.inflate(R.layout.item, parent, false);
        return new DefineViewHolder(view);
    }


    @Override
    public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position, IndexPath indexPath) {
        IndexPath path =  findIndexPathForPosition(position);
        if (holder instanceof DefineViewHolder) {
            ((DefineViewHolder)holder).setData(list.get(indexPath.row));
        }
    }

    @Override
    public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder, int position, IndexPath indexPath) {
        if (holder instanceof DefineViewHolder) {
            ((DefineViewHolder)holder).setData("第:"+indexPath+" 段 - header");
        }
    }

    @Override
    public void onBindFooterViewHolder(RecyclerView.ViewHolder holder, int position, IndexPath indexPath) {
        if (holder instanceof DefineViewHolder) {
            ((DefineViewHolder)holder).setData("第:"+indexPath+" 段 - Footer");
        }
    }

    static class DefineViewHolder extends RecyclerView.ViewHolder {

        TextView tvTitle;

        public DefineViewHolder(View itemView) {
            super(itemView);
            tvTitle = (TextView) itemView.findViewById(R.id.tv_title);
        }

        public void setData(String data) {
            tvTitle.setText(data);
        }

    }
}

关键方法:

 @Override
    public int getRow(int section) {
        return  section;
        //return 1;
    }

    @Override
    public int getSection() {
        return  list.size();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值