RecyclerView添加动态多个HeaderView 和FooterView

Posted IyangcLove

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RecyclerView添加动态多个HeaderView 和FooterView相关的知识,希望对你有一定的参考价值。

参考: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无法重用,数据越多问题越大。

以上是关于RecyclerView添加动态多个HeaderView 和FooterView的主要内容,如果未能解决你的问题,请参考以下文章

如何在 recyclerview 适配器中将动态视图添加到 android 布局

RecyclerView动态添加删除及点击事件

如何动态地将列表项添加到recyclerView?

在 RecyclerView 项目上添加多个 onClickListener

Android:以编程方式在片段中添加多个 RecyclerView

RecyclerView添加多个样式不同的Item布局