您的位置:首页 > 移动开发 > Android开发

一个精简的实现RecyclerView可添加header和footer的Demo

2016-08-27 15:38 603 查看

一个精简的实现RecyclerView可添加header和footer的Demo

实现思路很简单,就是把用户设置给RecyclerView的Adapter进行再封装,封装的内部类ExtraItemAdapter负责管理用户添加的header和footer。

在onBind等方法中计算出偏移后的position再调用用户设置的原生adapter。

public class MyRecyclerView extends RecyclerView {
protected ArrayList<View> mHeaderViews = new ArrayList<>();
protected ArrayList<View> mFooterViews = new ArrayList<>();
public MyRecyclerView(Context context) {
super(context);
}

public MyRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

public MyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

@Override
public void setAdapter(@NonNull Adapter adapter) {
super.setAdapter(new ExtraItemAdpater(adapter));
}

public void addHeaderView(@NonNull View headerView) {
addHeaderView(mHeaderViews.size(), headerView);
}

public void addHeaderView(int index, @NonNull View headerView) {
if (index >= 0 && index <= mHeaderViews.size()) {
mHeaderViews.add(index, headerView);
if (getAdapter() != null) {
getAdapter().notifyItemInserted(index);
}
}
}

public void removeHeaderView(@NonNull View headerView) {
int index = mHeaderViews.indexOf(headerView);
if (index != -1) {
mHeaderViews.remove(index);
if (getAdapter() != null) {
getAdapter().notifyItemRemoved(index);
}
}
}

public void addFooterView(@NonNull View footerView) {
addFooterView(mFooterViews.size(), footerView);
}

public void addFooterView(int index, @NonNull View footerView) {
if (index >= 0 && index <= mFooterViews.size()) {
mFooterViews.add(index, footerView);
if (getAdapter() != null) {
getAdapter().notifyItemInserted(mHeaderViews.size() + ((ExtraItemAdpater)getAdapter()).getNormaItemNum() + index);
}
}
}

public void removeFooterView(@NonNull View footerView) {
int index = mFooterViews.indexOf(footerView);
if (index != -1) {
mFooterViews.remove(index);
if (getAdapter() != null) {
getAdapter().notifyItemRemoved(getAdapter().getItemCount() - mFooterViews.size() + index);
}
}
}

public int getHeaderViewsCount() {
return mHeaderViews.size();
}

public int getFooterViewsCount() {
return mFooterViews.size();
}

private class ExtraItemAdpater extends Adapter {
private Adapter mAdapter;

public ExtraItemAdpater(Adapter adapter) {
this.mAdapter = adapter;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == Integer.MAX_VALUE) {
return new ExtraViewHolder(new FrameLayout(parent.getContext()));
}
return mAdapter.onCreateViewHolder(parent, viewType);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (position >= mHeaderViews.size() && position < (getItemCount() - mFooterViews.size())) {
mAdapter.onBindViewHolder(holder, position - mHeaderViews.size());
} else {
bindExtraViewHolder(holder, position);
}
}

@Override
public int getItemCount() {
return mHeaderViews.size() + mFooterViews.size() + getNormaItemNum();
}

@Override
public int getItemViewType(int position) {
if (position >= mHeaderViews.size() && position < (getItemCount() - mFooterViews.size())) {
return mAdapter.getItemViewType(position - mHeaderViews.size());
}
return Integer.MAX_VALUE;
}

@Override
public void registerAdapterDataObserver(AdapterDataObserver observer) {
if(this.mAdapter != null) {
this.mAdapter.registerAdapterDataObserver(observer);
}
super.registerAdapterDataObserver(observer);
}

@Override
public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
if(this.mAdapter != null) {
this.mAdapter.unregisterAdapterDataObserver(observer);
}
super.unregisterAdapterDataObserver(observer);
}

public int getNormaItemNum() {
return mAdapter.getItemCount();
}
}

public class ExtraViewHolder extends ViewHolder {
public ExtraViewHolder(View itemView) {
super(itemView);
}
}

private void bindExtraViewHolder(ViewHolder holder, int position) {
ExtraViewHolder extraViewHolder = (ExtraViewHolder) holder;
FrameLayout itemContainer = (FrameLayout) extraViewHolder.itemView;
View extraView;
if (position < mHeaderViews.size()) {
extraView = mHeaderViews.get(position);
} else {
int index = position - mHeaderViews.size() - ((ExtraItemAdpater)getAdapter()).getNormaItemNum();
extraView = mFooterViews.get(index);
}

// 防止复用item造成view重复添加
itemContainer.removeAllViews();
ViewGroup parentView = (ViewGroup) extraView.getParent();
if (parentView != null) {
parentView.removeAllViews();
}
itemContainer.addView(extraView);

// 让header和footer的LayoutParams兼容不同的布局,目前只考虑瀑布流布局
ViewGroup.LayoutParams lp = itemContainer.getLayoutParams();
if (lp == null) {
lp = MyRecyclerView.this.generateDefaultLayoutParams();
itemContainer.setLayoutParams(lp);
}
if (lp instanceof StaggeredGridLayoutManager.LayoutParams) {
((StaggeredGridLayoutManager.LayoutParams) lp).setFullSpan(true);
}
}
}


附加测试用的Adapter类

public class RVAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private final int NORMAL_ITEM_SIZE = 10;
private final int TYPE_NORMAL = 0;
private LayoutInflater mLayoutInflater;
public RVAdapter(Context context){
mLayoutInflater = LayoutInflater.from(context);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_NORMAL : {
return new NormalItemVH(mLayoutInflater.inflate(R.layout.item_layout, parent, false));
}
default:
return null;
}
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((NormalItemVH)holder).render(position + "");
}

@Override
public int getItemCount() {
return NORMAL_ITEM_SIZE;
}

@Override
public int getItemViewType(int position) {
return TYPE_NORMAL;
}

public static class NormalItemVH extends RecyclerView.ViewHolder {
public TextView mTextView;
public NormalItemVH(View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.textView);
}
public void render(String text) {
mTextView.setText("normal-" + text);
}
}
}


附加测试用的MainActivity(xml布局代码省略)

public class MainActivity extends AppCompatActivity {
private MyRecyclerView mRecyclerView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_main);
mRecyclerView = (MyRecyclerView) this.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setAdapter(new RVAdapter(this));
test();
}

private void test() {
for (int i = 0; i < 3; i ++) {
final View header = LayoutInflater.from(this).inflate(R.layout.extra_item_layout, new FrameLayout(this), false);
((TextView)header.findViewById(R.id.textView)).setText("header-" + i);
header.findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mRecyclerView.removeHeader(header);
}
});
mRecyclerView.addHeader(header);
}

for (int i = 0; i < 3; i ++) {
final View footer = LayoutInflater.from(this).inflate(R.layout.extra_item_layout, new FrameLayout(this), false);
((TextView)footer.findViewById(R.id.textView)).setText("footer-" + i);
footer.findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mRecyclerView.removeFooter(footer);
}
});
mRecyclerView.addFooter(footer);
}
}
}


下面是运行效果图



点击remove按钮会删除header或者footer
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android