当前位置:   article > 正文

RecyclerView展示多种布局_重写oncreateviewholder创建不同的viewholder

重写oncreateviewholder创建不同的viewholder

按照惯例 先看看效果图

多种布局效果图

简介

最上面是一个轮播图,然后下面是一个横向滑动的频道,然后下面就是一个GridView,再下面就是正常的布局显示了
当然这还不算是很复杂的布局,我这边只是讲讲原理和实现步骤,更多复杂布局可以根据这个去扩展

原理

给不同position的item设置不同的layout布局, 绑定不同的ViewHolder

实现步骤

1,定义不同的viewType常量(非必须)
2,在getItemViewType方法中根据position来返回不同的viewType
3,根据getItemViewType方法返回的不同的viewType在onCreateViewHolder创建不同的ViewHolder
4,onBindViewHolder方法里面用instanceof判断不同的ViewHolder来做不通的赋值处理
5,注意getItemCount的返回值

开撸代码

1,定义不同的viewType常量

上面的图片上可以看出,一共有4个type,轮播图,频道,美女,正常4个,下面是定义的常量

    private final int BANNER_VIEW_TYPE = 0;//轮播图
    private final int CHANNEL_VIEW_TYPE = 1;//频道
    private final int GIRL_VIEW_TYPE = 2;//美女
    private final int NORMAL_VIEW_TYPE = 3;//正常布局
  • 1
  • 2
  • 3
  • 4

2,在getItemViewType方法中根据position来返回不同的viewType

 /**
     * 获取item的类型
     *
     * @param position item的位置
     * @return item的类型
     * 有几种type就回在onCreateViewHolder方法中引入几种布局,也就是创建几个ViewHolder
     */
    @Override
    public int getItemViewType(int position) {
        /*
        区分item类型,返回不同的int类型的值
        在onCreateViewHolder方法中用viewType来创建不同的ViewHolder
         */
        if (position == 0) {//第0个位置是轮播图
                return BANNER_VIEW_TYPE;
        } else if (position == 1) {//第一个是频道布局
            return CHANNEL_VIEW_TYPE;
        } else if (position == 2) {//第2个位置是美女布局
            return GIRL_VIEW_TYPE;
        } else {//其他位置返回正常的布局
            return NORMAL_VIEW_TYPE;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

position就是每个item的位置,根据不同的位置来返回不同的布局type,可以根据你的需求自己穿插的来返回不同的viewType

3,根据getItemViewType方法返回的不同的viewType在onCreateViewHolder创建不同的ViewHolder
从这一步开始就是重头戏了

以轮播图为例子,每一个viewType都要有这几个步骤
a,写xml布局:既然有轮播图就肯定有轮播图的布局,我这里用的是第三方的轮播图,看布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.youth.banner.Banner
        android:id="@+id/banner"
        android:layout_width="match_parent"
        android:layout_height="175dp"
        app:delay_time="3000"
        app:scroll_time="1500"
        app:indicator_margin="5dp"
        app:indicator_height="6dp"
        app:indicator_width="6dp"
        app:indicator_drawable_selected="@color/colorPrimary"
        app:indicator_drawable_unselected="@color/colorAccent"
         />
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

没什么别的,就是你要展示的布局文件

b,创建ViewHolder内部类,继承RecyclerView.ViewHolder,在里面实例化你要赋值的控件

 /**
     * 轮播图的ViewHolder
     */
    public static class BannerHolder extends RecyclerView.ViewHolder {
        Banner banner;

        public BannerHolder(View itemView) {
            super(itemView);
            banner = (Banner) itemView.findViewById(R.id.banner);

        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

c,引入布局,new出ViewHolder并将引入的布局传递进去,在onCreateViewHolder方法里面

if (viewType == BANNER_VIEW_TYPE) {//如果viewType是轮播图就去创建轮播图的viewHolder
            View view = View.inflate(context, R.layout.item_banner, null);
            BannerHolder bannerHolder = new BannerHolder(view);
            return bannerHolder;
        }
  • 1
  • 2
  • 3
  • 4
  • 5

以上就是为一种布局创建ViewHodler

下面是完整的onCreateViewHolder方法里面判断不同的viewType创建不同的ViewHolder的代码

/**
     * 创建ViewHolder,根据getItemViewType方法里面返回的几种类型来创建
     *
     * @param viewType 就是getItemViewType返回的type
     * @return 返回自己创建的ViewHolder
     */
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view;
        if (viewType == BANNER_VIEW_TYPE) {//如果viewType是轮播图就去创建轮播图的viewHolder
            view = getView(R.layout.item_banner);
            BannerHolder bannerHolder = new BannerHolder(view);
            return bannerHolder;
        } else if (viewType == CHANNEL_VIEW_TYPE) {//频道的type
            view = getView(R.layout.item_channel);
            return new ChannelHolder(view);
        } else if (viewType == GIRL_VIEW_TYPE) {//美女
            view = getView(R.layout.item_girl);
            return new GirlHolder(view);
        } else {//正常
            view = getView(R.layout.item_normal);
            RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            view.setLayoutParams(lp);
            return new NormalHolder(view);
        }
    }

    /**
     * 用来引入布局的方法
     */
    private View getView(int view) {
        View view1 = View.inflate(context, view, null);
        return view1;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

4,onBindViewHolder方法里面用instanceof判断不同的ViewHolder来做不通的赋值处理

直接上代码了,注释很清楚了

@Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
        //判断不同的ViewHolder做不同的处理
        if (holder instanceof BannerHolder) {//轮播图
            BannerHolder bannerHolder = (BannerHolder) holder;
            //调用设置轮播图相关方法
            setBanner(bannerHolder);
        } else if (holder instanceof ChannelHolder) {//频道
            ChannelHolder channelHolder = (ChannelHolder) holder;
            //设置频道
            setChannel(channelHolder);
        } else if (holder instanceof GirlHolder) {//美女
            GirlHolder girlHolder = (GirlHolder) holder;
            GridViewAdapter adapter = new GridViewAdapter(context, girlList);
            girlHolder.gridView.setAdapter(adapter);
            girlHolder.gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Toast.makeText(context, "美女" + position, Toast.LENGTH_SHORT).show();
                }
            });
        } else if (holder instanceof NormalHolder) {//正常布局
            NormalHolder normalHolder = (NormalHolder) holder;
            normalHolder.textView.setText(normalList.get(position - 3));
            normalHolder.textView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(context, "点击了" + normalList.get(position - 3), Toast.LENGTH_SHORT).show();
                }
            });
        }

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

5,注意getItemCount的返回值
稍微不注意就越界了,+3是因为除了正常的布局还有3个不同的布局
如果是服务器请求数据的话就得不同的情况不同处理了

@Override
    public int getItemCount() {
        return normalList.size() + 3;
    }
  • 1
  • 2
  • 3
  • 4

下面贴出 整个RecyclerView的adapter的代码

package duanlian.multiplerecyclerviewdemo;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.youth.banner.Banner;
import com.youth.banner.BannerConfig;
import com.youth.banner.Transformer;
import com.youth.banner.loader.ImageLoader;

import java.util.List;
import java.util.Map;


/**
 * 程序猿: 段炼
 * 创建日期: 2017/4/19
 * 创建时间: 9:30
 * 本类功能:recyclerView的Adapter
 */

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context context;
    private List<String> picList;
    private List<Map<String, Object>> channelList;
    private List<Integer> girlList;
    private List<String> normalList;
    private final int BANNER_VIEW_TYPE = 0;//轮播图
    private final int CHANNEL_VIEW_TYPE = 1;//频道
    private final int GIRL_VIEW_TYPE = 2;//美女
    private final int NORMAL_VIEW_TYPE = 3;//正常布局

    public RecyclerAdapter(Context context, List<String> picList, List<Map<String, Object>> channelList,
                           List<Integer> girlList, List<String> normalList) {
        this.context = context;
        this.picList = picList;
        this.channelList = channelList;
        this.girlList = girlList;
        this.normalList = normalList;
    }

    /**
     * 获取item的类型
     *
     * @param position item的位置
     * @return item的类型
     * 有几种type就回在onCreateViewHolder方法中引入几种布局,也就是创建几个ViewHolder
     */
    @Override
    public int getItemViewType(int position) {
        /*
        区分item类型,返回不同的int类型的值
        在onCreateViewHolder方法中用viewType来创建不同的ViewHolder
         */
        if (position == 0) {//第0个位置是轮播图
            return BANNER_VIEW_TYPE;
        } else if (position == 1) {//第一个是频道布局
            return CHANNEL_VIEW_TYPE;
        } else if (position == 2) {//第2个位置是美女布局
            return GIRL_VIEW_TYPE;
        } else {//其他位置返回正常的布局
            return NORMAL_VIEW_TYPE;
        }
    }

    /**
     * 创建ViewHolder,根据getItemViewType方法里面返回的几种类型来创建
     *
     * @param viewType 就是getItemViewType返回的type
     * @return 返回自己创建的ViewHolder
     */
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view;
        if (viewType == BANNER_VIEW_TYPE) {//如果viewType是轮播图就去创建轮播图的viewHolder
            view = getView(R.layout.item_banner);
            BannerHolder bannerHolder = new BannerHolder(view);
            return bannerHolder;
        } else if (viewType == CHANNEL_VIEW_TYPE) {//频道的type
            view = getView(R.layout.item_channel);
            return new ChannelHolder(view);
        } else if (viewType == GIRL_VIEW_TYPE) {//美女
            view = getView(R.layout.item_girl);
            return new GirlHolder(view);
        } else {//正常
            view = getView(R.layout.item_normal);
            RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            view.setLayoutParams(lp);
            return new NormalHolder(view);
        }
    }

    /**
     * 用来引入布局的方法
     */
    private View getView(int view) {
        View view1 = View.inflate(context, view, null);
        return view1;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
        //判断不同的ViewHolder做不同的处理
        if (holder instanceof BannerHolder) {//轮播图
            BannerHolder bannerHolder = (BannerHolder) holder;
            //调用设置轮播图相关方法
            setBanner(bannerHolder);
        } else if (holder instanceof ChannelHolder) {//频道
            ChannelHolder channelHolder = (ChannelHolder) holder;
            //设置频道
            setChannel(channelHolder);
        } else if (holder instanceof GirlHolder) {//美女
            GirlHolder girlHolder = (GirlHolder) holder;
            GridViewAdapter adapter = new GridViewAdapter(context, girlList);
            girlHolder.gridView.setAdapter(adapter);
            girlHolder.gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Toast.makeText(context, "美女" + position, Toast.LENGTH_SHORT).show();
                }
            });
        } else if (holder instanceof NormalHolder) {//正常布局
            NormalHolder normalHolder = (NormalHolder) holder;
            normalHolder.textView.setText(normalList.get(position - 3));
            normalHolder.textView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(context, "点击了" + normalList.get(position - 3), Toast.LENGTH_SHORT).show();
                }
            });
        }

    }

    /**
     * 设置频道
     *
     * @param channelHolder
     */
    private void setChannel(ChannelHolder channelHolder) {
        //动态添加View
        for (int i = 0; i < channelList.size(); i++) {
            View view = View.inflate(context, R.layout.item_channel_view, null);
            ImageView ivLogo = (ImageView) view.findViewById(R.id.iv_logo);
            TextView tvChannel = (TextView) view.findViewById(R.id.tv_channel);
            Glide.with(context).load(channelList.get(i).get("pic")).into(ivLogo);
            tvChannel.setText(channelList.get(i).get("title").toString());
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            view.setLayoutParams(params);
            params.setMargins(24, 0, 24, 0);
            view.setTag(i);
            final int finalI = i;
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(context, channelList.get(finalI).get("title").toString(), Toast.LENGTH_SHORT).show();
                }
            });
            channelHolder.linearLayout.addView(view);
        }
    }

    /**
     * 设置轮播图
     *
     * @param bannerHolder
     */
    private void setBanner(BannerHolder bannerHolder) {
        //设置banner样式
        bannerHolder.banner.setBannerStyle(BannerConfig.CIRCLE_INDICATOR);
        //设置图片加载器
        bannerHolder.banner.setImageLoader(new GlideImageLoader());
        //设置图片集合
        bannerHolder.banner.setImages(picList);
        //设置banner动画效果
        bannerHolder.banner.setBannerAnimation(Transformer.Default);
        //设置标题集合(当banner样式有显示title时)
//            bannerHolder.banner.setBannerTitles(titles);
        //设置自动轮播,默认为true
        bannerHolder.banner.isAutoPlay(true);
        //设置轮播时间
//            bannerHolder.banner.setDelayTime(3500);
        //设置指示器位置(当banner模式中有指示器时)
        bannerHolder.banner.setIndicatorGravity(BannerConfig.CENTER);
        //banner设置方法全部调用完毕时最后调用
        bannerHolder.banner.start();
    }

    public class GlideImageLoader extends ImageLoader {
        @Override
        public void displayImage(Context context, Object path, ImageView imageView) {
            //Glide 加载图片简单用法
            Glide.with(context).load(path).into(imageView);
        }
    }

    @Override
    public int getItemCount() {
        return normalList.size() + 3;
    }

    /*****************************************下面是为不同的布局创建不同的ViewHolder*******************************************************/
    /**
     * 轮播图的ViewHolder
     */
    public static class BannerHolder extends RecyclerView.ViewHolder {
        Banner banner;

        public BannerHolder(View itemView) {
            super(itemView);
            banner = (Banner) itemView.findViewById(R.id.banner);

        }
    }

    /**
     * 频道列表的ViewHolder
     */
    public static class ChannelHolder extends RecyclerView.ViewHolder {
        LinearLayout linearLayout;

        public ChannelHolder(View itemView) {
            super(itemView);
            linearLayout = (LinearLayout) itemView.findViewById(R.id.ll_channel);

        }
    }

    /**
     * 美女的ViewHolder
     */
    public static class GirlHolder extends RecyclerView.ViewHolder {
        GridView gridView;

        public GirlHolder(View itemView) {
            super(itemView);
            gridView = (GridView) itemView.findViewById(R.id.gridview);
        }
    }

    /**
     * 正常布局的ViewHolder
     */
    public static class NormalHolder extends RecyclerView.ViewHolder {
        TextView textView;

        public NormalHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.text);
        }
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263

还有些细节就不说了,请下载demo

点击下载demo

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/174773
推荐阅读
相关标签
  

闽ICP备14008679号