Android RecyclerView 다양한 아 이 템 레이아웃 구현 방법

14608 단어 RecyclerViewitem배치
프로젝트 에서 목록 은 기본적으로 사용 되 지만 목록 을 표시 할 때 우리 가 필요 로 하 는 데 이 터 는 하나의 아 이 템 만 표시 해 야 할 수도 있 습 니 다.복잡 한 데이터 에 대해 서 는 다양한 아 이 템 이 필요 합 니 다.서로 다른 스타일 로 표시 하면 효과 가 좋 습 니 다.먼저 효 과 를 보 겠 습 니 다.


이 RecyclerView 에 여러 가지 아 이 템 이 표시 되 어 있 습 니 다.그러면 구체 적 으로 어떻게 실현 되 는 지 알 수 있 습 니 다.사실 RecyclerView 에서 우 리 는 getItemView Type()을 다시 쓸 수 있 습 니 다.이 방법 은 하나의 매개 변수 position 에 들 어가 현재 몇 번 째 아 이 템 임 을 표시 합 니 다.그리고 우 리 는 position 을 통 해 현재 아 이 템 대상 을 얻 은 다음 에 이 아 이 템 대상 이 그런 보기 가 필요 하 다 고 판단 할 수 있 습 니 다.int 형식의 보기 표 지 를 되 돌려 주 고 onCreatView Holder 방법 에서 레이아웃 을 도입 하면 다양한 아 이 템 을 표시 할 수 있 습 니 다.이렇게 많은 예 를 들 어 구체 적 인 예 를 살 펴 보 겠 습 니 다.

@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); 
  } 
} 
먼저 getItemView Type 이라는 방법 을 다시 썼 습 니 다.이 방법 에서 position 에 따라 item 대상 에 대해 판단 을 했 습 니 다.만약 에 item 대상 의 집합 크기 가 비어 있 으 면 빈 view 표지(여기 가 1)로 돌아 갑 니 다.만약 에 item 대상 이 null 이면 진도 표 지 를 되 돌려 줍 니 다.이것 은 주로 드 롭 다운 로드 를 실현 하 는 데 사 용 됩 니 다.만약 에 item 대상 유형 이 이미지 유형 에 속 하면그림 형식 에 대응 하 는 아 이 템 을 되 돌려 줍 니 다.이것 이 바로 효과 그림 의 첫 번 째 아 이 템 유형 입 니 다.그렇지 않 으 면 다른 유형,즉 효과 그림 의 다른 아 이 템 레이아웃 입 니 다.그리고 우 리 는 onCreatView Holder 에서 구체 적 으로 모든 유형 에 레이아웃 을 도입 합 니 다.

@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); 
  } 
} 
위의 코드 는 모든 view Type 에 해당 하 는 레이아웃 을 구체 적 으로 도입 하 는 것 입 니 다.그러면 기본적으로 여러 가지 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 공식 Swipe RefreshLayout,드 롭 다운 새로 고침,드 롭 다운 로드 가 완료 되 었 습 니 다.사실 쉬 워 요.그리고 약간 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); 
    } 
  } 
     
  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
마지막 으로 왜 ListView 대신 RecyclerView 를 사 용 했 는 지 말씀 드 리 겠 습 니 다.
ListView 를 사용 해 본 사람들 은 모두 알 고 있 습 니 다.ListView 에서 보기 캐 시 를 다시 사용 하려 면 getView()방법 에서 convertView 가 비어 있 는 지 수 동 으로 판단 해 야 합 니 다.비어 있 지 않 으 면 보기 캐 시 를 다시 사용 하고 비어 있 으 면 보 기 를 다시 불 러 옵 니 다.RecyclerView 는 ListView 의 Adapter 를 다시 봉인 한 것 과 같 습 니 다.ListView 를 수 동 으로 캐 시 여 부 를 판단 하 는 코드 를 RecyclerView 내부 에 봉 인 했 습 니 다.이 부분의 논 리 를 볼 수 없 게 하려 면 getItemCount()방법 을 통 해 RecyclerView 에 몇 가지 데이터 가 있 는 지 알려 주 고 onCreate ViewHolder()에 item 레이아웃 을 불 러 와 뷰 Holder 를 예화 한 다음 에 onBindViewHolder()에서 데이터 의 바 인 딩 을 완성 하면 됩 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기