最近会更新一些关于recycleview的使用教程哦。
第一篇,给recycleview添加header,footer,emptyview。
最近有开发一个列表,这个列表需要添加header和footer的功能。记录一下,避免每次开发都去查找相关代码。
代码示例:
(1)adapter:
public class MessageCenterAdapter extends RecyclerView.Adapter {
private List mDatas;
private Context mContext;
private View mHeaderView;
private View mFooterView;
private View mEmptyView;
private static final int sITEM_TYPE_NORMAL = 0;
private static final int sITEM_TYPE_HEADER = 1;
private static final int sITEM_TYPE_FOOTER = 2;
private static final int sITEM_TYPE_EMPTY = 3;
private final LayoutInflater mIinflater;
public MessageCenterAdapter(Context context, OnMsgClickListener onMsgClickListener) {
mContext = context;
this.onMsgClickListener = onMsgClickListener;
mDatas = new ArrayList<>();
mIinflater = LayoutInflater.from(mContext);
}
// 创建视图
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == sITEM_TYPE_HEADER) {
return new HeaderViewHolder(mHeaderView);
} else if (viewType == sITEM_TYPE_EMPTY) {
return new EmptyViewHolder(mEmptyView);
} else if (viewType == sITEM_TYPE_FOOTER) {
return new FooterViewHolder(mFooterView);
} else {
View contentView = mIinflater.inflate(R.layout.item_message_center, parent, false);
return new ContentViewHolder(contentView);
}
}
@Override
public int getItemViewType(int position) {
if (null != mHeaderView && position == 0) {
return sITEM_TYPE_HEADER;
}
if (null != mFooterView && position == getItemCount() - 1) {
return sITEM_TYPE_FOOTER;
}
if (null != mEmptyView && mDatas.size() == 0) {
return sITEM_TYPE_EMPTY;
}
return sITEM_TYPE_NORMAL;
}
// 为Item绑定数据
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int type = getItemViewType(position);
if (type == sITEM_TYPE_HEADER || type == sITEM_TYPE_FOOTER) {
return;
}
int realPos = getRealItemPosition(position);
if (type == sITEM_TYPE_EMPTY) {
((EmptyViewHolder) holder).tvEmpty.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (onMsgClickListener != null) {
onMsgClickListener.onEmptyItemClick();
}
}
});
} else {
((ContentViewHolder) holder).tvTitle.setText(mDatas.get(realPos).getTitle());
((ContentViewHolder) holder).tvDate.setText(mDatas.get(realPos).getDate());
((ContentViewHolder) holder).tvContent.setText(mDatas.get(realPos).getContent());
//最后一个不显示分割线
if (realPos == mDatas.size() - 1) {
((ContentViewHolder) holder).tvLine.setVisibility(View.GONE);
} else {
((ContentViewHolder) holder).tvLine.setVisibility(View.VISIBLE);
}
}
}
private int getRealItemPosition(int position) {
if (null != mHeaderView) {
return position - 1;
}
return position;
}
@Override
public int getItemCount() {
int itemCount = mDatas.size();
if (null != mEmptyView && itemCount == 0) {
itemCount++;
}
if (null != mHeaderView) {
itemCount++;
}
if (null != mFooterView) {
itemCount++;
}
return itemCount;
}
/**
* 设置数据
*
* @param datas
*/
public void setDatas(List datas) {
mDatas.clear();
mDatas.addAll(datas);
}
/**
* 添加头部
*
* @param view
*/
public void addHeaderView(View view) {
mHeaderView = view;
notifyItemInserted(0);
}
/**
* 判断是否有头部
*
* @return
*/
public boolean isHaveHeader() {
return mHeaderView != null;
}
/**
* 去除头部
*/
public void removeHeaderView() {
mHeaderView = null;
}
/**
* 添加空布局
*
* @param view
*/
public void addEmptyView(View view) {
mEmptyView = view;
}
/**
* 移除空布局
*/
public void removeEmptyView() {
mEmptyView = null;
}
/**
* 添加底部
*
* @param view
*/
public void addFooterView(View view) {
mFooterView = view;
}
/**
* 判断是否有底部
*
* @return
*/
public boolean isHaveFooter() {
return mFooterView != null;
}
/**
* 移除底部
*/
public void removeFooterView() {
mFooterView = null;
}
/**
* 内容viewholder
*/
class ContentViewHolder extends RecyclerView.ViewHolder {
TextView tvTitle;
TextView tvDate;
TextView tvContent;
View tvLine;
ContentViewHolder(View view) {
super(view);
tvTitle = view.findViewById(R.id.tv_title);
tvDate = view.findViewById(R.id.tv_date);
tvContent = view.findViewById(R.id.tv_content);
tvLine = view.findViewById(R.id.tv_line);
}
}
/**
* 空页面
*/
class EmptyViewHolder extends RecyclerView.ViewHolder {
TextView tvEmpty;
public EmptyViewHolder(@NonNull View view) {
super(view);
tvEmpty = view.findViewById(R.id.tv_empty);
}
}
/**
* 顶部
*/
class HeaderViewHolder extends RecyclerView.ViewHolder {
public HeaderViewHolder(@NonNull View view) {
super(view);
}
}
/**
* 底部
*/
class FooterViewHolder extends RecyclerView.ViewHolder {
public FooterViewHolder(@NonNull View view) {
super(view);
}
}
public interface OnMsgClickListener {
void onMsgItemClick();
void onEmptyItemClick();
}
public OnMsgClickListener onMsgClickListener;
}
(2)activity使用:
public class MessageFragment extends BaseFragment implements MessageCenterAdapter.OnMsgClickListener {
private View mRootView;
private RecyclerView mRecycleView;
private MessageCenterViewModel mMessageCenterViewModel;
private MessageCenterAdapter msgAdapter;
//避免多次执行notifyItemChanged
private boolean mChangeFlag;
private static Handler mHandler = new Handler();
private View mEmptyView;
private View footerView;
private View headerView;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mRootView = inflater.inflate(R.layout.fragment_message, container, false);
return mRootView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initView();
initObserver();
loadDatas();
}
private void initView() {
mRecycleView = mRootView.findViewById(R.id.rv_message);
final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecycleView.setLayoutManager(layoutManager);
msgAdapter = new MessageCenterAdapter(getActivity(), this);
headerView = LayoutInflater.from(getActivity()).inflate(R.layout.item_message_center_header, mRecycleView, false);
footerView = LayoutInflater.from(getActivity()).inflate(R.layout.item_message_center_footer, mRecycleView, false);
mEmptyView = LayoutInflater.from(getActivity()).inflate(R.layout.item_message_center_empty, mRecycleView, false);
msgAdapter.addHeaderView(headerView);
mRecycleView.setAdapter(msgAdapter);
// TODO: 2019/10/15 后面改成网络接口数据回来后删除
mHandler.removeCallbacks(mHeaderTipGoneRunable);
mHandler.postDelayed(mHeaderTipGoneRunable, 3000);
mRecycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//产生后动之后才判断要不要显示到底的提示
if (dy > 0) {
int lastCompletelyVisibleItemPosition = layoutManager.findLastCompletelyVisibleItemPosition();
if (lastCompletelyVisibleItemPosition == layoutManager.getItemCount() - 1) {
if (!mChangeFlag) {
mChangeFlag = true;
msgAdapter.addFooterView(footerView);
msgAdapter.notifyItemChanged(msgAdapter.getItemCount() - 1);
}
}
}
}
});
}
private void initObserver() {
mMessageCenterViewModel = ViewModelProviders.of(getActivity()).get(MessageCenterViewModel.class);
mMessageCenterViewModel.getmMessageCenterLiveData().observe(getActivity(), new Observer>() {
@Override
public void onChanged(List messageCenterBeans) {
if (isFromTry) {
msgAdapter.removeEmptyView();
msgAdapter.setDatas(messageCenterBeans);
} else {
msgAdapter.addEmptyView(mEmptyView);
}
msgAdapter.notifyDataSetChanged();
}
});
}
Runnable mHeaderTipGoneRunable = new Runnable() {
@Override
public void run() {
msgAdapter.removeHeaderView();
msgAdapter.notifyDataSetChanged();
}
};
/**
* 获取消息列表的数据
*/
private void loadDatas() {
mMessageCenterViewModel.getMessageData();
}
/**
* 消息item 点击
*/
@Override
public void onMsgItemClick() {
}
@Override
public void onDestroyView() {
super.onDestroyView();
mHandler.removeCallbacks(mHeaderTipGoneRunable);
}
/**
* 暂无数据点击需要重新加载数据
*/
@Override
public void onEmptyItemClick() {
isFromTry = true;
loadDatas();
}
boolean isFromTry;
}
本篇代码采用的是Google 的MVVP框架,如果跟你的框架不一样,可以替换不同的加载数据的方法,删掉数据加载和监听的代码,替换成你的,就可以啦。