轻松实现类试与 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();
}