使用RecyclerView结合jiaozivideoplayer去加载不同类型的布局

想做一个能够实现多种类型布局放在一个RecyclerView中的页面,Demo最终的效果是下面这个样子:

这里写图片描述

可以看到,整个列表中,有视频布局,纯文本的笑话布局,长图片布局,动态图片布局;最后两个可以合并在一个布局里去展示。

所以首先,要显示上面的东西需要用到下面这些控件:

1.节操播放器(大概是很久以前的名字了,这个控件经常改名字)
github地址:https://github.com/lipangit/JiaoZiVideoPlayer
使用方法是添加依赖:

compile 'cn.jzvd:jiaozivideoplayer:6.1.2'

2.Glide,这个就不谈了:

compile 'com.github.bumptech.glide:glide:3.7.0'

3.RecyclerView,这个更不谈了,反正和V7库什么的一起添加依赖吧。还有联网权限就不说了。

之前是使用的ListView去实现这个效果的,不过现在RecyclerView才是大势所趋呀(我是看《第二行代码》里面郭神说的),反正ListView能做的,RecyclerView都可以。

虽然使用过多次RecyclerView,但是具体怎么去实现这么一个效果还是有点小麻烦的,所以就上网看到了下面这两篇大佬(人人皆大佬,唯我一小生)的文章,简洁明了,蛮容易看懂:

RecyclerView用法(一)——展示多种类型Item数据
http://blog.csdn.net/cxc19890214/article/details/49226743

RecyclerView实现多种item布局
http://blog.csdn.net/zhumintao/article/details/53023920

想快速上手的小伙伴建议先去看上面的就OK了,我只是想记录一下我的学习成果,所以写的这篇文章。

如果是在ListView中去实现这样的效果,需要多写两个方法

    @Override  
    public int getItemViewType(int position) {  
        return super.getItemViewType(position);  
    }  

    @Override  
    public int getViewTypeCount() {  
        return super.getViewTypeCount();  
    }  

一个是获取item的类型,另外一个是获取所有类型的数量,如果有5种类型,下面那个方法就返回5。

但是在RecyclerView中,只能看得到第一个方法,而第二个方法就相当于onCreateViewHolder(ViewGroup parent, int viewType)中的第二个参数。

所以创建一个RecyclerView的适配器TypesNewsRecyclerAdapter;

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

之前只有一种数据的时候,上面的ViewHolder就是这种数据的ViewHolder,不过现在有多种数据了,ViewHolder自然不能写成某一种,而是需要写成RecyclerView.ViewHolder,然后同样让所有类型的ViewHolder的继承RecyclerView.ViewHolder。

然后我需要三种类型的ViewHolder,分别是视频,文本,图片,所以首先创建三个标识符:


    private static final int TYPE_VIDEO = 0;  //视频类型
    private static final int TYPE_IMAGE = 1;    //图片类型
    private static final int TYPE_TEXT = 2; //文本类型

接着在getItemViewType中分别给从网络返回的type数据赋值:

    @Override
    public int getItemViewType(int position) {
        ManyTypesNewsBean.ShowapiResBodyBean.PagebeanBean.ContentlistBean data = dataList.get(position);
        String type = data.getType();
        int itemViewType = -1;
        if ("41".equals(type)) {
            itemViewType = TYPE_VIDEO;
        } else if ("10".equals(type)) {
            itemViewType = TYPE_IMAGE;
        } else if ("29".equals(type)) {
            itemViewType = TYPE_TEXT;
        }
        return itemViewType;
    }

然后为每种类型创建对应的ViewHolder:

class VideoViewHolder extends RecyclerView.ViewHolder{

    public VideoViewHolder(View itemView) {
            super(itemView);
    }
}

class ImageViewHolder extends RecyclerView.ViewHolder{

    public ImageViewHolder(View itemView) {
            super(itemView);
    }
}

class TextViewHolder extends RecyclerView.ViewHolder{

    public TextViewHolder(View itemView) {
            super(itemView);
    }
}

可以从最上面的最终效果看到,每一种布局都有相同的部分,把这一部分的实例写在同一个类中,然后初始化布局写在同一个方法中,比如下面这样:

    //公共视图
    static class CommonView{
    ...
        //用户信息
        ImageView iv_headpic;
        TextView tv_name;
    ...
    }

    //初始化方法
    private void initCommonView(View itemView, CommonView commonView) {
    ...

    commonView.iv_headpic = (ImageView) itemView.findViewById(R.id.iv_headpic);
    commonView.tv_name = (TextView) itemView.findViewById(R.id.tv_name);
    ...
    }

接着非常简单的,在之前创建的各类型对应的ViewHolder把这些公共部分添加进去,同时初始化该类型特有的控件:

    class VideoViewHolder extends RecyclerView.ViewHolder{
        CommonView commonView = new CommonView();
        JZVideoPlayerStandard jcv_videoplayer; // 节操播放器

        public VideoViewHolder(View itemView) {
            super(itemView);
            //在这里实例化特有的
            jcv_videoplayer = (JZVideoPlayerStandard) itemView.findViewById(R.id.jcv_videoplayer);
            initCommonView(itemView, commonView);

        }

    }

    class ImageViewHolder extends RecyclerView.ViewHolder{
        CommonView commonView = new CommonView();
        ImageView iv_image_icon;

        public ImageViewHolder(View itemView) {
            super(itemView);
            iv_image_icon = (ImageView) itemView.findViewById(R.id.iv_image_icon);
            initCommonView(itemView, commonView);
        }
    }

    class TextViewHolder extends RecyclerView.ViewHolder{
        CommonView commonView = new CommonView();

        public TextViewHolder(View itemView) {
            super(itemView);
            initCommonView(itemView, commonView);
        }
    }

初始化布局基本上就完成了,接下来就是要把从网络获取的数据放到布局上,首先还是关于公共部分的数据获取,把所有公共视图的数据获取放在一个方法中,也可以避免很多重复的代码,比如:

    private void bindCommonData(CommonView view, ManyTypesNewsBean.ShowapiResBodyBean.PagebeanBean.ContentlistBean data) {
        if (data.getProfile_image() != null){
            Glide.with(context).load(data.getProfile_image())
                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .skipMemoryCache(false)
                    .error(R.drawable.user)
                    .into(view.iv_headpic);

        }
        if (data.getName() != null){
            view.tv_name.setText(data.getName());
        }
        view.tv_time_refresh.setText(data.getCreate_time());
       ...
    }

之后就是剩下的各类ViewHolder中的数据获取了,在onBindViewHolder方法中:

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ManyTypesNewsBean.ShowapiResBodyBean.PagebeanBean.ContentlistBean data = dataList.get(position);
        if (holder instanceof VideoViewHolder){
            VideoViewHolder videoViewHolder = (VideoViewHolder) holder;
            bindCommonData(videoViewHolder.commonView, data);

            videoViewHolder.jcv_videoplayer.setUp(data.getVideo_uri(), JZVideoPlayerStandard.SCREEN_WINDOW_NORMAL, "");
        } else if (holder instanceof ImageViewHolder){
            ImageViewHolder imageViewHolder = (ImageViewHolder) holder;
            bindCommonData(imageViewHolder.commonView, data);

            imageViewHolder.iv_image_icon.setImageResource(R.drawable.bg_item);
            if(data.getImage0() != null){
                Glide.with(context).load(data.getImage0()).placeholder(R.drawable.bg_item).error(R.drawable.bg_item).diskCacheStrategy(DiskCacheStrategy.ALL).into(imageViewHolder.iv_image_icon);
            }
        } else if (holder instanceof TextViewHolder){
            TextViewHolder textViewHolder = (TextViewHolder) holder;
            bindCommonData(textViewHolder.commonView, data);
        }

    }

需要注意到,上面节操播放器的用法,setUp这个方法接受三个参数,第一个是视频地址,第二个一种播放窗口的模式,第三个是视频的标题,没有就填”“,不能填null,不然会报错,节操播放器的控件在布局中差不多是这么用:

        <cn.jzvd.JZVideoPlayerStandard
            android:id="@+id/jcv_videoplayer"
            android:layout_width="match_parent"
            android:layout_height="220dp" />

最后是RecyclerView适配器的完整代码,关于布局的代码就不写了,因为非常非常多~~~:

public class TypesNewsRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final int TYPE_VIDEO = 0;  //视频类型
    private static final int TYPE_IMAGE = 1;    //图片类型
    private static final int TYPE_TEXT = 2; //文本类型
    private static final int TYPE_SOUND = 3;   //声音类型

    private Context context;
    private List<ManyTypesNewsBean.ShowapiResBodyBean.PagebeanBean.ContentlistBean> dataList;

    public TypesNewsRecyclerAdapter(Context context, List<ManyTypesNewsBean.ShowapiResBodyBean.PagebeanBean.ContentlistBean> dataList) {
        this.context = context;
        this.dataList = dataList;
    }


    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (context != null){
            this.context = parent.getContext();
        }

        View view;
        if(viewType == TYPE_VIDEO){
            view = View.inflate(context, R.layout.all_video_item, null);
            return new VideoViewHolder(view);
        } else if(viewType == TYPE_IMAGE){
            view = View.inflate(context, R.layout.all_image_item, null);
            return new ImageViewHolder(view);
        } else {
            view =View.inflate(context, R.layout.all_text_item, null);
            return new TextViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ManyTypesNewsBean.ShowapiResBodyBean.PagebeanBean.ContentlistBean data = dataList.get(position);
        if (holder instanceof VideoViewHolder){
            VideoViewHolder videoViewHolder = (VideoViewHolder) holder;
            bindCommonData(videoViewHolder.commonView, data);

            videoViewHolder.jcv_videoplayer.setUp(data.getVideo_uri(), JZVideoPlayerStandard.SCREEN_WINDOW_NORMAL, "");
        } else if (holder instanceof ImageViewHolder){
            ImageViewHolder imageViewHolder = (ImageViewHolder) holder;
            bindCommonData(imageViewHolder.commonView, data);

            imageViewHolder.iv_image_icon.setImageResource(R.drawable.bg_item);
            if(data.getImage0() != null){
                Glide.with(context).load(data.getImage0()).placeholder(R.drawable.bg_item).error(R.drawable.bg_item).diskCacheStrategy(DiskCacheStrategy.ALL).into(imageViewHolder.iv_image_icon);
            }
        } else if (holder instanceof TextViewHolder){
            TextViewHolder textViewHolder = (TextViewHolder) holder;
            bindCommonData(textViewHolder.commonView, data);
        }

    }

    private void bindCommonData(CommonView view, ManyTypesNewsBean.ShowapiResBodyBean.PagebeanBean.ContentlistBean data) {
        if (data.getProfile_image() != null){
            Glide.with(context).load(data.getProfile_image())
                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .skipMemoryCache(false)
                    .error(R.drawable.user)
                    .into(view.iv_headpic);

        }
        if (data.getName() != null){
            view.tv_name.setText(data.getName());
        }
        view.tv_time_refresh.setText(data.getCreate_time());
        view.tv_shenhe_ding_number.setText(data.getLove());
        view.tv_shenhe_cai_number.setText(data.getHate());
        view.tv_context.setText(data.getText());
    }


    @Override
    public int getItemViewType(int position) {
        ManyTypesNewsBean.ShowapiResBodyBean.PagebeanBean.ContentlistBean data = dataList.get(position);
        String type = data.getType();
        int itemViewType = -1;
        if ("41".equals(type)) {
            itemViewType = TYPE_VIDEO;
        } else if ("10".equals(type)) {
            itemViewType = TYPE_IMAGE;
        } else if ("29".equals(type)) {
            itemViewType = TYPE_TEXT;
        }
// else if ("31".equals(type)) {
//            itemViewType = TYPE_SOUND;
//        }
        return itemViewType;
    }

    @Override
    public int getItemCount() {
        return dataList.size();
    }

    class VideoViewHolder extends RecyclerView.ViewHolder{
        CommonView commonView = new CommonView();
        JZVideoPlayerStandard jcv_videoplayer;

        public VideoViewHolder(View itemView) {
            super(itemView);
            //在这里实例化特有的
            jcv_videoplayer = (JZVideoPlayerStandard) itemView.findViewById(R.id.jcv_videoplayer);
            initCommonView(itemView, commonView);

        }

    }

    class ImageViewHolder extends RecyclerView.ViewHolder{
        CommonView commonView = new CommonView();
        ImageView iv_image_icon;

        public ImageViewHolder(View itemView) {
            super(itemView);
            iv_image_icon = (ImageView) itemView.findViewById(R.id.iv_image_icon);
            initCommonView(itemView, commonView);
        }
    }

    class TextViewHolder extends RecyclerView.ViewHolder{
        CommonView commonView = new CommonView();

        public TextViewHolder(View itemView) {
            super(itemView);
            initCommonView(itemView, commonView);
        }
    }

    //公共视图
    static class CommonView{
        //用户信息
        ImageView iv_headpic;
        TextView tv_name;
        TextView tv_time_refresh;
        ImageView iv_right_more;

        //顶和赞
        TextView tv_shenhe_ding_number;
        TextView tv_shenhe_cai_number;

//        //下载栏
//        LinearLayout ll_download;

        //中间公共部分 -所有的都有
        TextView tv_context;
    }

    private void initCommonView(View itemView, CommonView commonView) {
        commonView.tv_context = (TextView) itemView.findViewById(R.id.tv_context);

        commonView.iv_headpic = (ImageView) itemView.findViewById(R.id.iv_headpic);
        commonView.tv_name = (TextView) itemView.findViewById(R.id.tv_name);
        commonView.tv_time_refresh = (TextView) itemView.findViewById(R.id.tv_time_refresh);
        commonView.iv_right_more = (ImageView) itemView.findViewById(R.id.iv_right_more);

        commonView.tv_shenhe_ding_number = (TextView) itemView.findViewById(R.id.tv_shenhe_ding_number);
        commonView.tv_shenhe_cai_number = (TextView) itemView.findViewById(R.id.tv_shenhe_cai_number);

//        commonView.ll_download = (LinearLayout) itemView.findViewById(R.id.ll_download);
    }
}

—————————————————————————————————————————————————————————

补充:给长图添加点击显示大图效果。

这就用到了自定义Dialog,在网上看到了一篇非常不错的文章,如下:

PhotoView+Glide+Dialog+ViewPager:打造轻量级的图片浏览方案
http://www.jianshu.com/p/629300228921

我照着文章做了一个结合PhotoView显示长图的Dialog,首先自定义Dialog的显示效果,在style中添加:

    <!--全屏背景半透明 dialog-->
    <style name="transparentBgDialog" parent="@android:style/Theme.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:backgroundDimEnabled">true</item>
        <item name="android:background">@android:color/transparent</item>
        <item name="android:windowNoTitle">true</item>
    </style>

然后自定义Dialog的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:gravity="center_horizontal"
             android:orientation="vertical"
             android:paddingBottom="5dp"
             android:paddingTop="5dp">
    <uk.co.senab.photoview.PhotoView
        android:id="@+id/pv_long"
        android:scaleType="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="15dp"
        android:layout_marginTop="15dp"/>
    <TextView
        android:id="@+id/tv_image_index"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textColor="@android:color/white"/>
</FrameLayout>

接着是自定义创建一个Config类,用于设置Dialog的宽和高:

public class  Config {
    public static int EXACT_SCREEN_HEIGHT;
    public static int EXACT_SCREEN_WIDTH;
}

接下来开始自定义Dialog:

public class ShowImagesDialog extends Dialog {

    private Context context;
    private View view ;
    private PhotoView photoView;
    String url;

    public ShowImagesDialog(@NonNull Context context, String url) {
        super(context, R.style.transparentBgDialog);  //这里用到了自定义Dialog的样式
        this.context = context;
        this.url = url;

        initView();
        initData();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(view);
        Window window = getWindow();
        WindowManager.LayoutParams wl = window.getAttributes();
        wl.x = 0;
        wl.y = 0;
        wl.height = Config.EXACT_SCREEN_HEIGHT;
        wl.width = Config.EXACT_SCREEN_WIDTH;
        wl.gravity = Gravity.CENTER;
        window.setAttributes(wl);
    }

    private void initView() {
        view = View.inflate(context, R.layout.dialog_image, null);
        photoView = (PhotoView) view.findViewById(R.id.pv_long);
    }

    private void initData(){
        PhotoViewAttacher.OnPhotoTapListener listener = new PhotoViewAttacher.OnPhotoTapListener() {
            @Override
            public void onPhotoTap(View view, float x, float y) {
                dismiss();
            }
        };

        photoView.setOnPhotoTapListener(listener);

        Glide.with(context)
                .load(url)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .placeholder(R.drawable.bg_item)
                .error(R.drawable.bg_item)
                .into(new SimpleTarget<GlideDrawable>() { //这个灰常重要,作用是让图片清晰地显示
                    @Override
                    public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
                        photoView.setImageDrawable(resource);
                    }
                });
    }
}

最后在TypesNewsRecyclerAdapter的onBindViewHolder方法中添加:

else if (holder instanceof ImageViewHolder){
            ImageViewHolder imageViewHolder = (ImageViewHolder) holder;
            bindCommonData(imageViewHolder.commonView, data);

            imageViewHolder.iv_image_icon.setImageResource(R.drawable.bg_item);
            if(data.getImage0() != null){
                Glide.with(context).load(data.getImage0()).placeholder(R.drawable.bg_item).error(R.drawable.bg_item).diskCacheStrategy(DiskCacheStrategy.RESULT).into(imageViewHolder.iv_image_icon);
                getDeviceDensity();
                if (data.getImage0().indexOf("gif") == -1){
                    imageViewHolder.iv_image_icon.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            new ShowImagesDialog(context, data.getImage0()).show();
                        }
                    });
                }
            }
        }

看一下效果吧!

这里写图片描述

猜你喜欢

转载自blog.csdn.net/asjqkkkk/article/details/78489245