RecyclerView添加动态多个HeaderView 和FooterView
程序员文章站
2022-05-04 19:53:48
...
参考:http://blog.csdn.net/qibin0506/article/details/49716795
因项目需求写了查询资料写了一个适配器基类
package com.example.asus.recyclerviewheader;
import android.content.Context;
import android.support.v4.util.SparseArrayCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
/**
* base rycAdapter class
*/
public abstract class BaseRycAdapter<VH extends BaseRycAdapter.BaseViewHolder, T> extends RecyclerView.Adapter<VH>
{
private Context baseCxt;
protected List<T> dataLists;
//默认itemView 点击事件开关
private boolean itemViewClickToggle = true;
// 设置大是为避免与itemType类型多时导致可能出现重复
private static final int BASE_ITEM_TYPE_HEADER = 100000;
private static final int BASE_ITEM_TYPE_FOOTER = 200000;
private SparseArrayCompat<View> headerViews = new SparseArrayCompat<>();
private SparseArrayCompat<View> footerViews = new SparseArrayCompat<>();
private ViewGroup mViewGroup;
public void addHeaderView(View view)
{
headerViews.put(headerViews.size() + BASE_ITEM_TYPE_HEADER, view);
}
public void addFooterView(View view)
{
footerViews.put(footerViews.size() + BASE_ITEM_TYPE_FOOTER, view);
}
public View getHeaderView(int index)
{
return (index >= 0 && headerViews.size() > index) ? headerViews.valueAt(index) : null;
}
public View getFooterView(int index)
{
return (index >= 0 && footerViews.size() > index) ? footerViews.valueAt(index) : null;
}
public void removeHeaderView(int index)
{
headerViews.removeAt(index);
}
public void removeFooterView(int index)
{
footerViews.removeAt(index);
}
@Override
public int getItemViewType(int position)
{
if(isHeaderViewPos(position))
return headerViews.keyAt(position);
else if(isFooterViewPos(position))
return footerViews.keyAt(getFootersCount() + position - getItemCount());
return super.getItemViewType(position);
}
@Override
public int getItemCount()
{
return headerViews.size() + dataLists.size() + footerViews.size();
}
abstract class BaseViewHolder extends RecyclerView.ViewHolder
{
BaseViewHolder(View itemView)
{
super(itemView);
if(isNormalItemView(itemView))
initItemView(itemView);
}
abstract void initItemView(View itemView);
}
@SuppressWarnings("WeakerAccess")
private boolean isNormalItemView(View itemView)
{
return !(headerViews.indexOfValue(itemView) != -1 || footerViews.indexOfValue(itemView) != -1);
}
/**
* GridLayoutManager布局时“Head”和“Foot”处理
*/
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView)
{
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if(manager instanceof GridLayoutManager)
{
final GridLayoutManager gridManager = ((GridLayoutManager)manager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup()
{
@Override
public int getSpanSize(int position)
{
return getItemViewType(position) >= BASE_ITEM_TYPE_HEADER ? gridManager.getSpanCount() : 1;
}
});
}
}
/**
* StaggeredGridLayoutManager布局时“Head”和“Foot”处理
*/
@Override
public void onViewAttachedToWindow(VH holder)
{
super.onViewAttachedToWindow(holder);
ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
if(lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams)
{
StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams)lp;
p.setFullSpan(getItemViewType(holder.getLayoutPosition()) >= BASE_ITEM_TYPE_HEADER);
}
}
private boolean isHeaderViewPos(int position)
{
return position < getHeadersCount();
}
private boolean isFooterViewPos(int position)
{
return position >= getItemCount() - getFootersCount();
}
public int getHeadersCount()
{
return headerViews.size();
}
public int getFootersCount()
{
return footerViews.size();
}
@Override
public VH onCreateViewHolder(ViewGroup parent, int viewType)
{
mViewGroup = parent;
baseCxt = parent.getContext();
return getVHolder(viewType);
}
@Override
public void onBindViewHolder(final VH holder, int position)
{
//判断位置是头或者尾部则直接返回
if(getItemViewType(position) >= BASE_ITEM_TYPE_HEADER)
return;
if(onItemClickListener != null && itemViewClickToggle)
holder.itemView.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
if(itemViewClickToggle)
onItemClickListener.onItemClick(holder.itemView, (holder.getLayoutPosition() - headerViews.size()));
}
});
onBindViewData(holder, (holder.getLayoutPosition() - headerViews.size()));
}
/**
* 子类通过该方法设置item显示数据
*
* @param holder 泛型VH
* @param position item position
*/
abstract void onBindViewData(VH holder, int position);
/**
* 反射获取ViewHolder
*
* @param viewType itemView 类型
* @return 对应类型ViewHolder
*/
@SuppressWarnings("unchecked")
private VH getVHolder(int viewType)
{
try
{
View itemView;
if(headerViews.get(viewType) != null)
itemView = headerViews.get(viewType);
else if(footerViews.get(viewType) != null)
itemView = footerViews.get(viewType);
else
{
LayoutInflater inflater = LayoutInflater.from(baseCxt);
itemView = inflater.inflate(getLayoutResId(), mViewGroup, false);
}
Class aClass = getClass();
Type genType = aClass.getGenericSuperclass();
Type[] params = ((ParameterizedType)genType).getActualTypeArguments();
Class vhClass = (Class)params[0];
Constructor constructor = vhClass.getDeclaredConstructor(aClass, View.class);
return (VH)constructor.newInstance(this, itemView);
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
}
/**
* 获取itemView,子类实现
*/
public abstract int getLayoutResId();
public List<T> getDataLists()
{
return dataLists;
}
public void setDataLists(List<T> dataLists)
{
this.dataLists = dataLists;
}
//点击监听,可自行添加长按
interface OnItemClickListener
{
void onItemClick(View view, int position);
}
public boolean isItemViewClickToggle()
{
return itemViewClickToggle;
}
public void setItemViewClickToggle(boolean itemViewClickToggle)
{
this.itemViewClickToggle = itemViewClickToggle;
}
public OnItemClickListener getOnItemClickListener()
{
return onItemClickListener;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener)
{
this.onItemClickListener = onItemClickListener;
}
private OnItemClickListener onItemClickListener;
}
使用时继承并实现方法即可
package com.example.asus.recyclerviewheader;
import android.view.View;
import android.widget.TextView;
/**
* demo Adapter
*/
public class MainRycAdapter extends BaseRycAdapter<MainRycAdapter.MainViewHolder, BaseData>
{
// public class BaseData implements Serializable
// {
// private String baseDataStr = "";
//
// public String getBaseDataStr()
// {
// return baseDataStr;
// }
//
// public void setBaseDataStr(String baseDataStr)
// {
// this.baseDataStr = baseDataStr;
// }
// }
/**
* 设置正常数据
*
* @param holder holder
* @param position position
*/
@Override
void onBindViewData(MainViewHolder holder, int position)
{
BaseData dataStr = dataLists.get(position);
holder.textView.setText(dataStr.getBaseDataStr());
}
/**
* itemView layout
*/
@Override
public int getLayoutResId()
{
return R.layout.item;
}
/**
* ViewHolder
*/
class MainViewHolder extends BaseRycAdapter.BaseViewHolder
{
TextView textView;
public MainViewHolder(View itemView)
{
super(itemView);
}
@Override
void initItemView(View itemView)
{
textView = (TextView)itemView.findViewById(R.id.item_tv);
}
}
}
在Activity中添加
package com.example.asus.recyclerviewheader;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.CountDownTimer;
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.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
public class MainActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.ryc);
ArrayList<BaseData> baseDatas = new ArrayList<>();
for(int i = 0; i < 4; i++)
{
BaseData baseData = new BaseData();
baseData.setBaseDataStr(("data" + i));
baseDatas.add(baseData);
}
final MainRycAdapter myAdapter = new MainRycAdapter();
myAdapter.setDataLists(baseDatas);
for(int i = 0; i < 2; i++)
{
TextView head = new TextView(this);
head.setText("head_i-" + i);
head.setGravity(Gravity.CENTER);
head.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 30));
TextView foot = new TextView(this);
foot.setText("foot_i-" + i);
foot.setGravity(Gravity.CENTER);
foot.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 100));
myAdapter.addHeaderView(head);
myAdapter.addFooterView(foot);
}
myAdapter.setOnItemClickListener(new BaseRycAdapter.OnItemClickListener()
{
@Override
public void onItemClick(View view, int position)
{
Log.e("TAG", "click position = " + position);
}
});
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.addItemDecoration(new RecycleViewDivider(this, GridLayoutManager.VERTICAL));
//recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
//recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
recyclerView.setAdapter(myAdapter);
new CountDownTimer(2000, 2000)
{
@Override
public void onTick(long millisUntilFinished)
{
}
@Override
public void onFinish()
{
int headersCount = myAdapter.getHeadersCount();
for(int i = 0; i < headersCount; i++)
{
View headerView = myAdapter.getHeaderView(i);
if(i != 0)
{
headerView.setBackgroundColor(Color.RED);
ViewGroup.LayoutParams layoutParams = headerView.getLayoutParams();
layoutParams.height = 200;
headerView.setLayoutParams(layoutParams);
((TextView)headerView).setText("延时操作更改文本显示 - - index = " + i);
}
}
myAdapter.removeHeaderView(0);
myAdapter.notifyItemRemoved(0);
}
}.start();
}
}
Activity布局就一个RecyclerView 没什么特别的地方,还有个问题就是尽量不要用滚动条嵌套的问题解决HeaderView这种问题,因为嵌套会导致item无法重用,数据越多问题越大。