对RecyclerView的ViewType的使用以及添加Foot和Head的心得

楼主小菜鸡,最近写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.有什么写的不好地方欢迎大家指出,我们共同成长:)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值