RecyclerView组件自定义分组
2016-11-17 09:26
375 查看
轻松实现类试与 header footer item等分组的Adapter组件。好用方便。
原理: 将每一个Item 从position 转化为section(段) row(列)数据格式,方便定位具体属于那一组的哪一个Item的数据。数据格式如下:
关键点一:
count的计算法,count 从以前的position现在复杂化了,应该包含每一段的header、item、 footer的总和,算法较复杂,这里讲定义为final不让重复写。
关键2:
header 和 footer的动态处理,动态的删减
关键3:
将position转化为indexpath的算法
完成上面的情况,就可以进行封装了:
全码:
使用方法:
继承基类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(); }
相关文章推荐
- 【Android 仿微信通讯录 导航分组列表-下】自定义View为RecyclerView打造右侧索引导航栏IndexBar
- Android 自定义RecyclerView (替代ListView的最新组件)实现真正的Gallery效果
- HeaderView、FooterView、刷新、加载更多,支持自定义组装的RecyclerView组件
- 自定义图片缩放组件—ImageZoomView
- 几个经常需要自定义的组件:UIScrollview、UItextView、UIButton
- 自定义组件之【柱状图】详解 已封装成View
- 新书内容连载(1):自定义Android组件之带图像的TextView
- 自定义Android组件之带图像的TextView
- 开源组件:DEMO学习-DWinterTabDemo:自定义tab+viewpager
- 自定义组件之【柱状图】详解 已封装成View
- C#自定义网格组件(DataGridView)实现数据分组、排序
- 关于自定义组件-以apidemo中的LabelView进行讲解
- Android自定义View设定到FrameLayout布局中实现多组件显示
- 几个经常需要自定义的组件:UIScrollview、UItextView、UIButton
- iOS开发 自定义tableView样式(使用代码/使用Interface Builder)、分组显示、给TableView增加索引、给TableView增加SearchBar
- 自定义Android组件之带图像的TextView
- 自定义Android组件之带图像的TextView(转)
- (转)自定义Android组件之带图像的TextView
- 自定义组件—LoadingProcessView
- android 让TextView支持的Html标签实现自定义时钟显示组件DigitalClock