RecyclerView实现加载多种Item布局

前言

好久没写博客,是时候写写博客了,前面一个月都在找实习、学校实训事情忙都忙不过来,跑完之后还要去反省,今天哪里没做对?哪里还需要完善?自己的知识哪里还需要巩固?等等,牢骚话就不发了,步入正题!

背景

最近学校实训,要完成一个大的V电影的仿制,我就做了,其中涉及到很多的Android知识点,对这个项目感兴趣的可以点击这里 然后看项目的源代码!这个项目中就涉及到一个知识就是RecyclerView加载多种Item布局。

正文

首先,我们要明确RecyclerView中加载数据源的Where,那就是在Adapter适配器中,既然需要适配器,当然我们就要重写适配器,然后让其适应我们的数据源,所以我们需要让我们的适配器继承RecyclerView的Adapter

public class LatestRecyclerAdapter extends RecyclerView.Adapter<>{}

这儿有个尖括号,那说明需要在Adapter中放入泛型,使用过RecyclerView的应该知道,这儿确定了泛型,那就在Adapter中方法的属性也变成相应的泛型,这样就会使RecyclerView只能加载一种ViewHolder,也就是一种样式的子项,所以我们这需要用RecyclerView自带的ViewHolder,然后在具体方法中进行判断,根据不同的情况加载不同的布局,这样我们就实现加载多种样式的子项

public class LatestRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {}

既然有多种样式的子项,所以我们需要针对不同的子项写ViewHolder,如下
ViewHolder:

class AdverViewHolder extends RecyclerView.ViewHolder {

    public AdverViewHolder(View itemView) {
        super(itemView);
        mContainer = ((ViewPager) itemView.findViewById(R.id.fragment_latest_item_adver_container));
        mIndicator = ((RadioGroup) itemView.findViewById(R.id.fragment_latest_item_adver_indicator));
    }

}
class NormalViewHolder extends RecyclerView.ViewHolder {

    ImageView mNormalImage;
    TextView mNormalTopic;
    View mNormalDiving;
    TextView mNormalTitle;
    TextView mNormalInfo;

    public NormalViewHolder(View itemView) {
        super(itemView);
        mNormalImage = (ImageView) itemView.findViewById(R.id.fragment_latest_item_normal_img);
        mNormalTopic = (TextView) itemView.findViewById(R.id.fragment_latest_item_normal_topic);
        mNormalDiving = itemView.findViewById(R.id.fragment_latest_item_normal_diving);
        mNormalTitle = (TextView) itemView.findViewById(R.id.fragment_latest_item_normal_title);
        mNormalInfo = (TextView) itemView.findViewById(R.id.fragment_latest_item_normal_info);
    }

}

class LoadViewHolder extends RecyclerView.ViewHolder {

    ProgressBar progressBar;
    TextView message;

    public LoadViewHolder(View itemView) {
        super(itemView);
        progressBar = (ProgressBar) itemView.findViewById(R.id.fragment_latest_item_load_progress);
        message = (TextView) itemView.findViewById(R.id.fragment_latest_item_load_msg);
    }

}

然后我们会在RecyclerView的getItemViewType方法根据不同的情况返回不同的标志位,例如:

@Override
public int getItemViewType(int position) {
    if (position == 0) {
        return LatestAdapterParams.ADVER_VIEW;
    } else if (position == normalData.size()) {
        return LatestAdapterParams.EMPTY_VIEW;
    } else {
        return super.getItemViewType(position);
    }
}

因为我的广告是第一个位置显示,所以当position等于0时,就返回一个已赋值的广告标志位(ADVER_VIEW),当数据源显示完了,说明需要加载数据,所以我又返回的是空标志位(EMPTY_VIEW)然后在onCreateViewHolder方法中进行判断标志位,根据不同的标志位,我们创建不同的ViewHolder,然后让ViewHolder与其布局进行绑定

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view;
    if (viewType == LatestAdapterParams.ADVER_VIEW) {
        view = LayoutInflater.from(context).inflate(R.layout.fragment_latest_item_adver, parent, false);
        AdverViewHolder adverViewHolder = new AdverViewHolder(view);
        mContainer.setAdapter(new FragmentViewPagerAdapter(fManager, getAdverData()));
        mContainer.addOnPageChangeListener(this);
        mContainer.setOnTouchListener(this);
        return adverViewHolder;
    } else if (viewType == LatestAdapterParams.EMPTY_VIEW) {
        view = LayoutInflater.from(context).inflate(R.layout.fragment_latest_item_load, parent, false);
        return new LoadViewHolder(view);
    } else {
        view = LayoutInflater.from(context).inflate(R.layout.fragment_latest_item_normal, parent, false);
        final NormalViewHolder normalViewHolder = new NormalViewHolder(view);
        normalViewHolder.mNormalImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = normalViewHolder.getAdapterPosition();
                LatestNormalDataBean bean = normalData.get(position - 1);
                Intent intent = new Intent(v.getContext(), ItemActivity.class);
                Bundle bundle = new Bundle();
                bundle.putString("DATA_FROM", AllPageTypeParams.HOME_NORMAL_PAGE);
                bundle.putSerializable("NORMAL_DATA", bean);
                intent.putExtra("DATA", bundle);
                v.getContext().startActivity(intent);
            }
        });
        return normalViewHolder;
    }
}

然后具体的实现,就在onBindViewHolder方法中,例如:

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (holder instanceof AdverViewHolder) {
        mIndicator.removeAllViews();
        if (adverData != null) {
            for (int i = 0; i < adverData.size(); i++) {
                mIndicator.addView(getRadioButton());
            }
        } else {
            for (int i = 0; i < LatestAdapterParams.ADVER_DEFAULT_NUM; i++) {
                mIndicator.addView(getRadioButton());
            }
        }
        mContainer.setCurrentItem(1);
        RadioButton childOne = ((RadioButton) mIndicator.getChildAt(0));
        childOne.setChecked(true);
    } else if (holder instanceof NormalViewHolder) {
        NormalViewHolder normalViewHolder = (NormalViewHolder) holder;
        LatestNormalDataBean normalDataBean = normalData.get(position - 1);

        x.image().bind(normalViewHolder.mNormalImage, normalDataBean.getImage());
        normalViewHolder.mNormalTitle.setText(normalDataBean.getTitle());

        if (normalDataBean.getIs_album() == 0) {
            normalViewHolder.mNormalTopic.setVisibility(View.INVISIBLE);
            normalViewHolder.mNormalDiving.setVisibility(View.INVISIBLE);
            normalViewHolder.mNormalInfo.setText(normalDataBean.getCates().get(0).getCatename() + " / " + normalDataBean.getDuration() / 60 + "'" + normalDataBean.getDuration() % 60 + "''");
        } else {
            normalViewHolder.mNormalTopic.setVisibility(View.VISIBLE);
            normalViewHolder.mNormalDiving.setVisibility(View.VISIBLE);
            normalViewHolder.mNormalInfo.setText(normalDataBean.getApp_fu_title());
        }
    } else if (holder instanceof LoadViewHolder) {
        /**
         * 上拉加载进度条的接口,其中可以写加载更多的不同情况
         */
        RequestParams requestParams = new RequestParams(HttpRequestParams.HOST_URL + HttpRequestParams.LATEST_NORMAL_PATH + "?p=" + LatestAdapterParams.NORMAL_PAGE_NUM);
        x.http().get(requestParams, new Callback.CommonCallback<String>() {
            @Override
            public void onSuccess(String result) {
                Gson gson = new Gson();
                LatestNormalBean latestNormalBean = gson.fromJson(result, LatestNormalBean.class);
                List<LatestNormalDataBean> normalDataBeen = latestNormalBean.getData();
                updateLatestNormalData(normalDataBeen);
                ++LatestAdapterParams.NORMAL_PAGE_NUM;
            }

            @Override
            public void onError(Throwable ex, boolean isOnCallback) {

            }

            @Override
            public void onCancelled(CancelledException cex) {

            }

            @Override
            public void onFinished() {

            }
        });
    }
}

如果想看具体的代码,请点击这里

图片如下

android RecyclerView实现列表图片叠加 recyclerview加载多个list_ide

最后我想说的,你可以借鉴下这位小哥的博客,我的代码中涉及到了xUtils框架、点击事件等无关代码,所以有可能代码有点多和繁琐!