RecyclerView实现多种item布局
2016-11-03 22:39
344 查看
在项目中列表是基本都会用到的,然而在显示列表时,我们需要的数据可能需要不止一种item显示,对于复杂的数据就需要多种item,以不同的样式显示出来,这样效果是很棒的,我们先看一下效果
我们可以看到,这个RecyclerView中有多种item显示出来,那么具体怎么实现呢,其实在RecyclerView中,我们可以重写方法getItemViewType(),这个方法会传进一个参数position表示当前是第几个Item,然后我们可以通过position拿到当前的Item对象,然后判断这个item对象需要那种视图,返回一个int类型的视图标志,然后在onCreatViewHolder方法中给引入布局,这样就能够实现多种item显示了,讲了这么多我们看一下具体的例子
整个过程基本就是这样,这种方式在项目中经常会用到,我们就可以这样去处理,下拉加载更多就可以这样实现,在加载完数据后再往对象集合中传入null,然后判断如果出现null就加载progressBar布局,再加上Google官方的SwipeRefreshLayout,下拉刷新,上拉加载就搞定了,其实很容易,而且也有点Material Design 的感觉~~~~~~
看下Adapter的全部代码
package com.zmt.e_read.Adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.zmt.e_read.Module.News;
import com.zmt.e_read.Module.OnItemClickListener;
import com.zmt.e_read.R;
import com.zmt.e_read.Utils.ProgressViewHolder;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* Created by Dangelo on 2016/9/27.
*/
public class NewsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int EMPTY_VIEW = 1;
private final int PROGRESS_VIEW = 2;
private final int IMAGE_VIEW = 3;
private Context context;
private List<News> list;
private OnItemClickListener clickListener;
public NewsAdapter(Context context, List<News> list, OnItemClickListener clickListener) {
this.context = context;
this.list = list;
this.clickListener = clickListener;
}
public void addOnItemClickListener(OnItemClickListener clickListener){
this.clickListener = clickListener;
}
@Override
public int getItemViewType(int position) {
if(list.size() == 0){
return EMPTY_VIEW;
} else if(list.get(position) == null){
return PROGRESS_VIEW;
} else if(list.get(position).getType().equals(News.IMAGE_NEWS)){
return IMAGE_VIEW;
} else {
return super.getItemViewType(position);
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if(viewType == PROGRESS_VIEW){
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.progressbar_item, parent, false);
return new ProgressViewHolder(view);
} else if(viewType == EMPTY_VIEW){
return null;
} else if(viewType == IMAGE_VIEW){
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.image_news_item, parent, false);
return new ImageViewHolder(view);
} else {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, parent, false);
return new NewsViewHolder(view);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickListener.onItemClick(v, position);
}
});
if(holder instanceof NewsViewHolder){
NewsViewHolder viewHolder = (NewsViewHolder)holder;
viewHolder.title.setText(list.get(position).getTitle());
viewHolder.time.setText(list.get(position).getTime());
/**
* Glide加载图片
*/
Glide.with(context).load(list.get(position).getImageUrl().get(0))
.override(dpToPx(72), dpToPx(72)).centerCrop().into(viewHolder.image);
if(list.get(position).getType().equals(News.TEXT_NEWS)){
viewHolder.digest.setText(list.get(position).getDigest());
} else {
viewHolder.digest.setText("");
}
} else if(holder instanceof ImageViewHolder){
ImageViewHolder viewHolder = (ImageViewHolder)holder;
viewHolder.title.setText(list.get(position).getTitle());
viewHolder.time.setText(list.get(position).getTime());
setItemImage(viewHolder, list, position);
} else if(holder instanceof ProgressViewHolder){
ProgressViewHolder viewHolder = (ProgressViewHolder)holder;
viewHolder.progressBar.setIndeterminate(true);
}
}
public void setItemImage(ImageViewHolder viewHolder, List<News> list, int position){
viewHolder.imageMiddle.setVisibility(View.VISIBLE);
viewHolder.imageRight.setVisibility(View.VISIBLE);
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
if(list.get(position).getImageUrl().size() == 1){
Glide.with(context).load(list.get(position).getImageUrl().get(0))
.override(displayMetrics.widthPixels - dpToPx(10), dpToPx(90))
.centerCrop().into(viewHolder.imageLeft);
viewHolder.imageMiddle.setVisibility(View.GONE);
viewHolder.imageRight.setVisibility(View.GONE);
} else if(list.get(position).getImageUrl().size() == 2){
int imageWidth = (displayMetrics.widthPixels - dpToPx(20)) / 2;
Glide.with(context).load(list.get(position).getImageUrl().get(0))
.override(imageWidth, dpToPx(90))
.centerCrop().into(viewHolder.imageLeft);
Glide.with(context).load(list.get(position).getImageUrl().get(1))
.override(imageWidth, dpToPx(90))
.centerCrop().into(viewHolder.imageMiddle);
viewHolder.imageRight.setVisibility(View.GONE);
} else if(list.get(position).getImageUrl().size() >= 3){
int imageWidth = (displayMetrics.widthPixels - dpToPx(30)) / 3;
Glide.with(context).load(list.get(position).getImageUrl().get(0))
.override(imageWidth, dpToPx(90))
.centerCrop().into(viewHolder.imageLeft);
Glide.with(context).load(list.get(position).getImageUrl().get(1))
.override(imageWidth, dpToPx(90))
.centerCrop().into(viewHolder.imageMiddle);
Glide.with(context).load(list.get(position).getImageUrl().get(2))
.override(imageWidth, dpToPx(90))
.centerCrop().into(viewHolder.imageRight);
}
}
@Override
public int getItemCount() {
return list.size();
}
public int dpToPx(float dp){
float px = context.getResources().getDisplayMetrics().density;
return (int)(dp * px + 0.5f);
}
class NewsViewHolder extends RecyclerView.ViewHolder{
@BindView(R.id.news_title)TextView title;
@BindView(R.id.news_digest)TextView digest;
@BindView(R.id.news_time)TextView time;
@BindView(R.id.news_src)ImageView image;
public NewsViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
class ImageViewHolder extends RecyclerView.ViewHolder{
@BindView(R.id.news_title) TextView title;
@BindView(R.id.image_left) ImageView imageLeft;
@BindView(R.id.image_right) ImageView imageRight;
@BindView(R.id.image_middle) ImageView imageMiddle;
@BindView(R.id.news_time) TextView time;
public ImageViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
<pre name="code" class="java"> class ProgressViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.progressBar) ProgressBar progressBar;
@BindView(R.id.textView) TextView textView;
public ProgressViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}}
项目地址:https://github.com/xiyouZmt/E-Read
我们可以看到,这个RecyclerView中有多种item显示出来,那么具体怎么实现呢,其实在RecyclerView中,我们可以重写方法getItemViewType(),这个方法会传进一个参数position表示当前是第几个Item,然后我们可以通过position拿到当前的Item对象,然后判断这个item对象需要那种视图,返回一个int类型的视图标志,然后在onCreatViewHolder方法中给引入布局,这样就能够实现多种item显示了,讲了这么多我们看一下具体的例子
@Override public int getItemViewType(int position) { if(list.size() == 0){ return EMPTY_VIEW; } else if(list.get(position) == null){ return PROGRESS_VIEW; } else if(list.get(position).getType().equals(News.IMAGE_NEWS)){ return IMAGE_VIEW; } else { return super.getItemViewType(position); } }首先我们重写了getItemViewType这个方法,在这个方法中根据position对item对象做了一些判断,如果存储item对象的集合大小为空,返回空view标识(这里为1),如果item对象为null,返回进度条标识,这个主要是用于实现下拉加载更多,如果item对象类型属于图片类型,就返回图片类型对应的Item,这个就是效果图中的第一个Item类型,否则就是其它类型,也就是效果图中的另一种item布局,然后我们在onCreatViewHolder中具体的为每一种类型引入其布局
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; if(viewType == PROGRESS_VIEW){ view = LayoutInflater.from(parent.getContext()).inflate(R.layout.progressbar_item, parent, false); return new ProgressViewHolder(view); } else if(viewType == EMPTY_VIEW){ return null; } else if(viewType == IMAGE_VIEW){ view = LayoutInflater.from(parent.getContext()).inflate(R.layout.image_news_item, parent, false); return new ImageViewHolder(view); } else { view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, parent, false); return new NewsViewHolder(view); } }上面的代码就是具体为每种viewType引入其对应的布局,这样就基本实现了多种item布局,但是仅仅是这些还不够,因为我们还要对每种item设置数据,所以还要对每种item写一个VIewHolder来为item显示数据
class NewsViewHolder extends RecyclerView.ViewHolder{ @BindView(R.id.news_title)TextView title; @BindView(R.id.news_digest)TextView digest; @BindView(R.id.news_time)TextView time; @BindView(R.id.news_src)ImageView image; public NewsViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } } class ImageViewHolder extends RecyclerView.ViewHolder{ @BindView(R.id.news_title) TextView title; @BindView(R.id.image_left) ImageView imageLeft; @BindView(R.id.image_right) ImageView imageRight; @BindView(R.id.image_middle) ImageView imageMiddle; @BindView(R.id.news_time) TextView time; public ImageViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } } class ProgressViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.progressBar) ProgressBar progressBar; @BindView(R.id.textView) TextView textView; public ProgressViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } }上面就是item对应的几个ViewHolder,判断viewHolder属于那种对象,然后在onBindViewHolder中根据对应的ViewHolder对其控件设置数据并显示
@Override public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clickListener.onItemClick(v, position); } }); if(holder instanceof NewsViewHolder){ NewsViewHolder viewHolder = (NewsViewHolder)holder; viewHolder.title.setText(list.get(position).getTitle()); viewHolder.time.setText(list.get(position).getTime()); /** * Glide加载图片 */ Glide.with(context).load(list.get(position).getImageUrl().get(0)) .override(dpToPx(72), dpToPx(72)).centerCrop().into(viewHolder.image); if(list.get(position).getType().equals(News.TEXT_NEWS)){ viewHolder.digest.setText(list.get(position).getDigest()); } else { viewHolder.digest.setText(""); } } else if(holder instanceof ImageViewHolder){ ImageViewHolder viewHolder = (ImageViewHolder)holder; viewHolder.title.setText(list.get(position).getTitle()); viewHolder.time.setText(list.get(position).getTime()); setItemImage(viewHolder, list, position); } else if(holder instanceof ProgressViewHolder){ ProgressViewHolder viewHolder = (ProgressViewHolder)holder; viewHolder.progressBar.setIndeterminate(true); } }
整个过程基本就是这样,这种方式在项目中经常会用到,我们就可以这样去处理,下拉加载更多就可以这样实现,在加载完数据后再往对象集合中传入null,然后判断如果出现null就加载progressBar布局,再加上Google官方的SwipeRefreshLayout,下拉刷新,上拉加载就搞定了,其实很容易,而且也有点Material Design 的感觉~~~~~~
看下Adapter的全部代码
package com.zmt.e_read.Adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.zmt.e_read.Module.News;
import com.zmt.e_read.Module.OnItemClickListener;
import com.zmt.e_read.R;
import com.zmt.e_read.Utils.ProgressViewHolder;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* Created by Dangelo on 2016/9/27.
*/
public class NewsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int EMPTY_VIEW = 1;
private final int PROGRESS_VIEW = 2;
private final int IMAGE_VIEW = 3;
private Context context;
private List<News> list;
private OnItemClickListener clickListener;
public NewsAdapter(Context context, List<News> list, OnItemClickListener clickListener) {
this.context = context;
this.list = list;
this.clickListener = clickListener;
}
public void addOnItemClickListener(OnItemClickListener clickListener){
this.clickListener = clickListener;
}
@Override
public int getItemViewType(int position) {
if(list.size() == 0){
return EMPTY_VIEW;
} else if(list.get(position) == null){
return PROGRESS_VIEW;
} else if(list.get(position).getType().equals(News.IMAGE_NEWS)){
return IMAGE_VIEW;
} else {
return super.getItemViewType(position);
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if(viewType == PROGRESS_VIEW){
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.progressbar_item, parent, false);
return new ProgressViewHolder(view);
} else if(viewType == EMPTY_VIEW){
return null;
} else if(viewType == IMAGE_VIEW){
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.image_news_item, parent, false);
return new ImageViewHolder(view);
} else {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, parent, false);
return new NewsViewHolder(view);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickListener.onItemClick(v, position);
}
});
if(holder instanceof NewsViewHolder){
NewsViewHolder viewHolder = (NewsViewHolder)holder;
viewHolder.title.setText(list.get(position).getTitle());
viewHolder.time.setText(list.get(position).getTime());
/**
* Glide加载图片
*/
Glide.with(context).load(list.get(position).getImageUrl().get(0))
.override(dpToPx(72), dpToPx(72)).centerCrop().into(viewHolder.image);
if(list.get(position).getType().equals(News.TEXT_NEWS)){
viewHolder.digest.setText(list.get(position).getDigest());
} else {
viewHolder.digest.setText("");
}
} else if(holder instanceof ImageViewHolder){
ImageViewHolder viewHolder = (ImageViewHolder)holder;
viewHolder.title.setText(list.get(position).getTitle());
viewHolder.time.setText(list.get(position).getTime());
setItemImage(viewHolder, list, position);
} else if(holder instanceof ProgressViewHolder){
ProgressViewHolder viewHolder = (ProgressViewHolder)holder;
viewHolder.progressBar.setIndeterminate(true);
}
}
public void setItemImage(ImageViewHolder viewHolder, List<News> list, int position){
viewHolder.imageMiddle.setVisibility(View.VISIBLE);
viewHolder.imageRight.setVisibility(View.VISIBLE);
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
if(list.get(position).getImageUrl().size() == 1){
Glide.with(context).load(list.get(position).getImageUrl().get(0))
.override(displayMetrics.widthPixels - dpToPx(10), dpToPx(90))
.centerCrop().into(viewHolder.imageLeft);
viewHolder.imageMiddle.setVisibility(View.GONE);
viewHolder.imageRight.setVisibility(View.GONE);
} else if(list.get(position).getImageUrl().size() == 2){
int imageWidth = (displayMetrics.widthPixels - dpToPx(20)) / 2;
Glide.with(context).load(list.get(position).getImageUrl().get(0))
.override(imageWidth, dpToPx(90))
.centerCrop().into(viewHolder.imageLeft);
Glide.with(context).load(list.get(position).getImageUrl().get(1))
.override(imageWidth, dpToPx(90))
.centerCrop().into(viewHolder.imageMiddle);
viewHolder.imageRight.setVisibility(View.GONE);
} else if(list.get(position).getImageUrl().size() >= 3){
int imageWidth = (displayMetrics.widthPixels - dpToPx(30)) / 3;
Glide.with(context).load(list.get(position).getImageUrl().get(0))
.override(imageWidth, dpToPx(90))
.centerCrop().into(viewHolder.imageLeft);
Glide.with(context).load(list.get(position).getImageUrl().get(1))
.override(imageWidth, dpToPx(90))
.centerCrop().into(viewHolder.imageMiddle);
Glide.with(context).load(list.get(position).getImageUrl().get(2))
.override(imageWidth, dpToPx(90))
.centerCrop().into(viewHolder.imageRight);
}
}
@Override
public int getItemCount() {
return list.size();
}
public int dpToPx(float dp){
float px = context.getResources().getDisplayMetrics().density;
return (int)(dp * px + 0.5f);
}
class NewsViewHolder extends RecyclerView.ViewHolder{
@BindView(R.id.news_title)TextView title;
@BindView(R.id.news_digest)TextView digest;
@BindView(R.id.news_time)TextView time;
@BindView(R.id.news_src)ImageView image;
public NewsViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
class ImageViewHolder extends RecyclerView.ViewHolder{
@BindView(R.id.news_title) TextView title;
@BindView(R.id.image_left) ImageView imageLeft;
@BindView(R.id.image_right) ImageView imageRight;
@BindView(R.id.image_middle) ImageView imageMiddle;
@BindView(R.id.news_time) TextView time;
public ImageViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
<pre name="code" class="java"> class ProgressViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.progressBar) ProgressBar progressBar;
@BindView(R.id.textView) TextView textView;
public ProgressViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}}
项目地址:https://github.com/xiyouZmt/E-Read
相关文章推荐
- [置顶] RecyclerView实现加载多种条目类型,仿新闻列表多种item布局.
- Android RecyclerView实现多种item布局的方法
- Kotlin实战(二): 实现RecyclerView多种Item布局
- Android 中RecyclerView多种item布局的写法(头布局+脚布局)
- RecyclerView实现多种布局样式
- 使用RecyclerView实现两种不同Item布局
- 优雅实现RecyclerView多种布局
- ListView 显示多种itemView布局的简单实现
- Android RecyclerView多个Item布局的实现(可实现头部底部)
- Android学习笔记之RecyclerView(二)-异布局Item实现
- RecyclerView(四)——用RecyclerView实现多种布局
- RecyclerView 实现多种布局(上半部Gridview样式,下半部Listview样式)以及多种数据类型实现不同布局
- RecyclerView显示多种Item布局
- RecyclerView多种item布局
- Android RecyclerView使用详解(实现多种布局)
- 基于RecyclerView实现的实现多样化的item样式——类似IM即时通讯聊天界面的布局效果
- RecyclerView加载多种item布局
- RecyclerView实现多种Item,最优雅的方式,getItemViewType(以即时通讯app为例子)
- RecyclerView的Item多种类型的选择之普通方法实现
- 封装RecyclerView Adapter 实现可添加多个header和footer,可设置loadingView,低耦合的多种布局。