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

来源:互联网 发布:适合程序员的壁纸 编辑:程序博客网 时间:2024/06/05 03:09
楼主小菜鸡,最近写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 Viewprivate static final int TYPE_FOOTER = 1;  //FootViewprivate static final int TYPE_HEADER = 2;  //HeadViewpublic static final int SKIP_TRACKS_TYPE = 233;private int load_more_status = 0;//上拉加载更多状态-默认为0private 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;}@Overridepublic 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);}@Overridepublic 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);}@Overridepublic int getItemViewType(int position) {    if (position < getHeadViewCount()) return TYPE_HEADER;    if (position >= tracks.size() + getHeadViewCount()) return TYPE_FOOTER;    return TYPE_NORMAL;}@Overridepublic 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.有什么写的不好地方欢迎大家指出,我们共同成长:)
原创粉丝点击