您的位置:首页 > 运维架构

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

2017-11-09 14:19 197 查看
想做一个能够实现多种类型布局放在一个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();
}
});
}
}
}


看一下效果吧!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: