1. 程式人生 > >RecyclerView實現多種item佈局

RecyclerView實現多種item佈局

在專案中列表是基本都會用到的,然而在顯示列表時,我們需要的資料可能需要不止一種item顯示,對於複雜的資料就需要多種item,以不同的樣式顯示出來,這樣效果是很棒的,我們先看一下效果

我們可以看到,這個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);
        }
    }
}