您的位置:首页 > 其它

对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.有什么写的不好地方欢迎大家指出,我们共同成长:)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐