RecyclerView添加头尾布局方式有多种,一般常用的方式是利用ItemViewType,将头尾布局当做指定类型的item成为RecyclerView的子元素,这里面由于只涉及到RecyclerView基础方法,故直接上代码
先制作一个基类
import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<BaseRecyclerAdapter.BaseRecyclerViewHolder> {
/**
* normal item view type
*/
public static final int TYPE_NORMAL = 0;
/**
* header view type
*/
public static final int TYPE_HEADER = 1;
/**
* footer view type
*/
public static final int TYPE_FOOTER = 2;
private View mHeaderView;
private View mFooterView;
private OnItemClickListener onItemClickListener;
public List<T> mData = new ArrayList<>();
public void setData(List<T> data) {
if (data == null) {
mData.clear();
return;
}
mData.clear();
mData.addAll(data);
}
public T getItemData(int dataPosition) {
T res = null;
if (dataPosition < mData.size()) {
res = mData.get(dataPosition);
}
return res;
}
public void clearData() {
if (mData != null) {
mData.clear();
}
}
public int getDataSize() {
return mData.size();
}
public void setOnItemClickListener(OnItemClickListener li) {
onItemClickListener = li;
}
/**
* Add header view
*
* @param headerView
*/
public void setHeaderView(View headerView) {
mHeaderView = headerView;
notifyItemInserted(0);
}
/**
* Add header view res
*
* @param c,layoutId
*/
public void setHeaderView(Context c, int layoutId) {
if (c == null && layoutId < 0) {
return;
}
mHeaderView = LayoutInflater.from(c).inflate(layoutId, (ViewGroup) null);
notifyItemInserted(0);
}
/**
* Get header view
*
* @return
*/
public View getHeaderView() {
return mHeaderView;
}
/**
* Add footer view
*
* @param footerView
*/
public void setFooterView(View footerView) {
this.mFooterView = footerView;
notifyItemInserted(getItemCount() - 1);
}
/**
* Add footer view res
*
* @param c,layoutId
*/
public void setFooterView(Context c, int layoutId) {
if (c == null && layoutId < 0) {
return;
}
this.mFooterView = LayoutInflater.from(c).inflate(layoutId, (ViewGroup) null);
notifyItemInserted(getItemCount() - 1);
}
/**
* Get footer view
*
* @return
*/
public View getFooterView() {
return this.mFooterView;
}
@Override
public int getItemViewType(int position) {
if (mHeaderView != null && position == 0) {
return TYPE_HEADER;
}
if (mFooterView != null && position == getItemCount() - 1) {
return TYPE_FOOTER;
}
return TYPE_NORMAL;
}
/**
* get item data real position
*
* @param holder
* @return
*/
private int getRealPosition(BaseRecyclerViewHolder holder) {
int position = holder.getPosition();
return mHeaderView == null ? position : position - 1;
}
@Override
public BaseRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (mHeaderView != null && viewType == TYPE_HEADER) {
return new HeaderViewHolder(mHeaderView);
}
if (mFooterView != null && viewType == TYPE_FOOTER) {
return new FooterViewHolder(mFooterView);
}
return onCreateRecyclerViewHolder(parent, viewType);
}
public void onBindViewHolder(BaseRecyclerViewHolder holder, int position) {
//如果是header footer view就直接返回,不需要绑定数据
if (getItemViewType(position) == TYPE_HEADER) {
return;
}
if (getItemViewType(position) == TYPE_FOOTER) {
return;
}
final int pos = getRealPosition(holder);
final T data = mData.get(pos);
bindData(holder, position);
if (onItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onItemClickListener.onItemClick(pos, data);
}
});
}
}
@Override
public int getItemCount() {
int count = mData.size();
if (mHeaderView != null) {
count++;
}
if (mFooterView != null) {
count++;
}
return count;
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager) {
final GridLayoutManager gridLayoutManager = ((GridLayoutManager) manager);
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (getItemViewType(position) == TYPE_HEADER) {
return gridLayoutManager.getSpanCount();
}
if (getItemViewType(position) == TYPE_FOOTER) {
return gridLayoutManager.getSpanCount();
}
return 1;
}
});
}
//LinearLayoutManager不需要设置
}
/**
* Create item view holder
*
* @param parent
* @param viewType
* @return
*/
protected abstract BaseRecyclerViewHolder onCreateRecyclerViewHolder(ViewGroup parent, int viewType);
/**
* Bind data.
*
* @param holder
* @param position
*/
public abstract void bindData(BaseRecyclerViewHolder holder, int position);
static abstract class BaseRecyclerViewHolder extends RecyclerView.ViewHolder {
public BaseRecyclerViewHolder(View itemView) {
super(itemView);
findView(itemView);
}
public abstract void findView(View v);
}
/**
* header view ViewHolder
*/
class HeaderViewHolder extends BaseRecyclerViewHolder {
public HeaderViewHolder(View itemView) {
super(itemView);
}
@Override
public void findView(View v) {
}
}
/**
* footer view ViewHolder
*/
class FooterViewHolder extends BaseRecyclerViewHolder {
public FooterViewHolder(View itemView) {
super(itemView);
}
@Override
public void findView(View v) {
}
}
/**
* item 点击事件接口
*
* @param <T>position 数据实际位置
*/
public interface OnItemClickListener<T> {
void onItemClick(int position, T data);
}
}
使用时:
1.直接继承BaseRecyclerAdapter
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.mvp.demo.R;
import java.util.Random;
public class CustomAdapter extends BaseRecyclerAdapter<Integer> {
Context mContext;
public CustomAdapter(Context c) {
this.mContext = c;
}
@Override
protected BaseRecyclerViewHolder onCreateRecyclerViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_layout, null);
return new CustomHolder(view);
}
@Override
public void bindData(BaseRecyclerViewHolder holder, int position) {
CustomHolder customHolder = (CustomHolder) holder;
customHolder.content.setText(mData.get(position - 1) + "");
}
class CustomHolder extends BaseRecyclerViewHolder {
public RelativeLayout container;
public TextView content;
public CustomHolder(View itemView) {
super(itemView);
}
@Override
public void findView(View v) {
container = itemView.findViewById(R.id.container);
content = itemView.findViewById(R.id.content);
ViewGroup.LayoutParams layoutParams = container.getLayoutParams();
layoutParams.height = mContext.getResources().getDisplayMetrics().widthPixels / 3;
container.setLayoutParams(layoutParams);
Random random = new Random();
int ranColor = 0xff000000 | random.nextInt(0x00ffffff);
content.setBackgroundColor(ranColor);
}
}
}
2.在activity中初始化:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
initData();
}
private void initData() {
mData.clear();
for (int i = 0; i < 8; i++) {
mData.add(i);
}
mCustomAdapter.setData(mData);
mRecyclerView.setAdapter(mCustomAdapter);
}
private void init() {
mRecyclerView = findViewById(R.id.recycler);
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));
mCustomAdapter = new CustomAdapter(this);
mCustomAdapter.setFooterView(this, R.layout.header_footer_layout);
mCustomAdapter.setHeaderView(this, R.layout.header_footer_layout);
mCustomAdapter.setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener<Integer>() {
@Override
public void onItemClick(int position, Integer data) {
Toast.makeText(getApplicationContext(), data + "", Toast.LENGTH_SHORT).show();
}
});
}
布局文件:
header_footer_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="@android:color/darker_gray">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Header or Footer" />
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
item_layout.xml:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/content"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:textColor="@android:color/white"
android:gravity="center"
/>
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
效果图:
recycler示例.png
当然我们也可以将头尾布局放到List数据里,设置不同的type,达到同样的效果
网友评论