对RecyclerView的ViewType的使用以及添加Foot和Head的心得
2017-06-15 17:20
375 查看
楼主小菜鸡,最近写recycleView碰到了对foot和head的需求. 楼主以前用recycleView都是像ListView一样的写法,对viewType的使用还不够深入,这次掉坑里狠狠地悟了一波. 先说说坑:之前写foot还挺简单的,但是当写head的时候碰到一个问题.head的position会和Normal的position发生一定的冲突.(主要还是代码不够严谨) 这个bug卡了很久,最后一点点细细地解耦核查,总算是解决了,这里发个博客记录一下. 这里我将head和foot作为View通过set方法.从外部传进来,将其ViewHolder也作为外部类来传进来,同时也方便复用.重点是代码简洁许多.直接上代码吧,总结放结尾好了.setFoot这样看起来挺像listView的:)
public class TestAdapter extends RecyclerView.Adapter {
private static final int TYPE_NORMAL = 0; //Item View private static final int TYPE_FOOTER = 1; //FootView private static final int TYPE_HEADER = 2; //HeadView public static final int SKIP_TRACKS_TYPE = 233; private int load_more_status = 0;//上拉加载更多状态-默认为0 private List<Track> tracks = new ArrayList<>(); private Album album;//头部的数据 private View mHeaderView;//头部的控件,用set方法在外部设置 private View mFooterView;//尾部的控件,用set方法在外部设置 public void setHeaderView(View headerView) { mHeaderView = headerView; notifyItemInserted(0); } public View getHeaderView() { return mHeaderView; } public View getFooterView() { return mFooterView; } public void setFooterView(View mFooterView) { this.mFooterView = mFooterView; } private int getHeadViewCount() { return mHeaderView == null ? 0 : 1; } private int getFootViewCount() { return mFooterView == null ? 0 : 1; } private int width; private AlbumsRecyclerItemClickListener itemClickListener; public TestAdapter(List<Track> tracks, Album album, AlbumsRecyclerItemClickListener itemClickListener, int width) { this.width = width; this.album = album; this.itemClickListener = itemClickListener; this.tracks = tracks; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {//在oncreate的时候分辨type来分配holder if (viewType == TYPE_HEADER) return new AlbumsTrackHeadViewHolder(mHeaderView); if (viewType == TYPE_FOOTER) return new AlbumsTrackFootViewHolder(mFooterView); View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler_album_track, parent, false); return new AlbumsTrackViewHolder(view); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { //之前看了某同学的代码,他这边用的是viewType == TYPE来进行判断.结果可能不够严谨,在强转的时候发生了错误.这边用instanceof就解决了这个问题 if (holder instanceof AlbumsTrackHeadViewHolder) { setHeadHolder(holder); return; } if (holder instanceof AlbumsTrackFootViewHolder) { setFootHolder(holder); return; } setNormalHolder(holder); } @Override public int getItemViewType(int position) { if (position < getHeadViewCount()) return TYPE_HEADER; if (position >= tracks.size() + getHeadViewCount()) return TYPE_FOOTER; return TYPE_NORMAL; } @Override public int getItemCount() { return tracks.size() + getHeadViewCount() + getFootViewCount(); } private int getRealPosition(RecyclerView.ViewHolder holder) { int position = holder.getLayoutPosition(); return mHeaderView == null ? position : position - 1; } public void changeMoreStatus(int status) { load_more_status = status; notifyDataSetChanged(); } public void addMoreItem(List<Track> newDatas) { tracks.addAll(newDatas); notifyDataSetChanged(); } private void setNormalHolder(RecyclerView.ViewHolder holder) {//设置主体的内容 AlbumsTrackViewHolder albumHolder = (AlbumsTrackViewHolder) holder; final int pos = getRealPosition(albumHolder); if (tracks.size() != 0) { albumHolder.tvTitle.setText(tracks.get(pos).getTrackTitle()); final String intro = tracks.get(pos).getTrackIntro(); if (intro.equals("")) { albumHolder.tvContent.setVisibility(View.GONE); } else { albumHolder.tvContent.setVisibility(View.VISIBLE); albumHolder.tvContent.setText(intro); } if (tracks.get(pos).getCoverUrlMiddle().length() != 0) { Glide.with(albumHolder.ivTitlePic.getContext()).load(tracks.get(pos).getCoverUrlMiddle()).into(albumHolder.ivTitlePic); } albumHolder.tvPlayCount.setText(TextUtils.getThousand(tracks.get(pos).getPlayCount())); albumHolder.tvEstimatedTrackCount.setText(TextUtils.getMinutes(tracks.get(pos).getDuration())); albumHolder.llItemAlbum.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); } } private void setHeadHolder(RecyclerView.ViewHolder holder) {//设置head的具体内容 AlbumsTrackHeadViewHolder headViewHolder = (AlbumsTrackHeadViewHolder) holder; headViewHolder.tvTrackHeadTitle.setText(album.getAlbumTitle()); headViewHolder.tvTrackHeadIntroduce.setText(album.getAlbumIntro()); Glide.with(headViewHolder.ivTrackHeadIcon.getContext()).load(album.getCoverUrlMiddle()).into(headViewHolder.ivTrackHeadIcon); } private void setFootHolder(RecyclerView.ViewHolder footViewHolder) {//设置foot的具体内容 AlbumsTrackFootViewHolder headViewHolder = (AlbumsTrackFootViewHolder) footViewHolder; switch (load_more_status) { case AlbumRecyclerAdapter.PULLUP_LOAD_MORE: headViewHolder.tvFootLording.setText("上拉加载更多..."); break; case AlbumRecyclerAdapter.LOADING_MORE: headViewHolder.progressBar.setVisibility(View.VISIBLE); headViewHolder.tvFootLording.setText("正在加载更多数据..."); break; case AlbumRecyclerAdapter.NO_CONTENT: headViewHolder.tvFootLording.setText("已无更多内容"); headViewHolder.progressBar.setVisibility(View.INVISIBLE); break; } } private class AlbumsTrackViewHolder extends RecyclerView.ViewHolder { private TextView tvTitle; private TextView tvContent; private TextView tvPlayCount; private TextView tvEstimatedTrackCount; private ImageView ivTitlePic; private LinearLayout llItemAlbum; AlbumsTrackViewHolder(View itemView) { super(itemView); if (itemView == mHeaderView) return; if (itemView == mFooterView) return; llItemAlbum = (LinearLayout) itemView.findViewById(R.id.llItemAlbum); ivTitlePic = (ImageView) itemView.findViewById(R.id.ivTitlePic); tvTitle = (TextView) itemView.findViewById(R.id.tvTitle); tvContent = (TextView) itemView.findViewById(R.id.tvContent); tvPlayCount = (TextView) itemView.findViewById(R.id.tvPlayCount); tvEstimatedTrackCount = (TextView) itemView.findViewById(R.id.tvEstimatedCount); tvEstimatedTrackCount.setMaxWidth((int) (width * 0.8)); tvPlayCount.setMaxWidth((int) (width * 0.8)); } }
}
总结:第一.既然加了Foot和Head.一定不要忘了修改整体count的数量.否则肯定会出现数组越界报错.
第二.head和foot都是通过判断position的位置来进行锁定的,所以在getItemViewType的时候一定要仔细.同时,不要忘了,既然都是通过position来锁定位置,那么主体的内容就不能直接通过position来粗暴地确定了(会被head或者foot给挤开).
在之前就是因为我的不严谨导致了头部占了第一位,然后主体内容变成了第二个,然后到底部就数组越界了.担心算错position,最好封装一个方法用于确定主体里要用到的数据的position.有什么写的不好地方欢迎大家指出,我们共同成长:)
相关文章推荐
- RecyclerView的使用以及下拉刷新自动加载(添加点击事件、头部)
- 一款下拉刷新以及上拉加载的控件库,扩展性强,使用简单。并附带有可以添加 header 和 footer 的 Recyclerview
- 使用RecyclerView实现滑动添加、滑动删除,以及瀑布流、ListView、GridView的转换
- RecyclerView 添加head view头部 和foot view尾部、设置水平horizontal时左侧布局和右侧布局
- RecyclerView详细使用(二):Herder添加以及adpter封装
- RecyclerView 动画 (添加、删除动画 以及 加载item 时的动画)
- XRecyclerView:实现下拉刷新、滚动到底部加载更多以及添加header功能的RecyclerView
- Android中Recyclerview使用3----添加条目得到点击事件和长按事件
- Android适配器之 V7扩展包 RecyclerView 的使用以及万能适配器的封装实现
- 使用RecyclerView CardView相关问题 解决The hierarchy of the type is inconsistent问题
- RecyclerView的进阶使用,一个LayoutManger下添加多种布局
- Android中Recyclerview使用5----添加头部:RecyclerViewHeader
- RecyclerView的使用心得记录
- Android中Recyclerview使用6----添加条目得到点击事件和长按事件(另一种写法,较简单)
- RecyclerView使用(二)多种Item布局、添加点击事件
- 使用RecyclerView添加Header和Footer的方法
- Android RecyclerView使用(二) -给Item添加点击事件
- Android使用RecyclerView实现自定义列表、点击事件以及下拉刷新
- RecyclerView使用详解一代替ListView(点击事件,添加头布局,上拉刷新下拉加载)
- Android 简捷地为RecyclerView添加HeadView和FootView