使用RecyclerView结合jiaozivideoplayer去加载不同类型的布局
2017-11-09 14:19
197 查看
想做一个能够实现多种类型布局放在一个RecyclerView中的页面,Demo最终的效果是下面这个样子:
可以看到,整个列表中,有视频布局,纯文本的笑话布局,长图片布局,动态图片布局;最后两个可以合并在一个布局里去展示。
所以首先,要显示上面的东西需要用到下面这些控件:
1.节操播放器(大概是很久以前的名字了,这个控件经常改名字)
github地址:https://github.com/lipangit/JiaoZiVideoPlayer
使用方法是添加依赖:
2.Glide,这个就不谈了:
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中去实现这样的效果,需要多写两个方法
一个是获取item的类型,另外一个是获取所有类型的数量,如果有5种类型,下面那个方法就返回5。
但是在RecyclerView中,只能看得到第一个方法,而第二个方法就相当于onCreateViewHolder(ViewGroup parent, int viewType)中的第二个参数。
所以创建一个RecyclerView的适配器TypesNewsRecyclerAdapter;
之前只有一种数据的时候,上面的ViewHolder就是这种数据的ViewHolder,不过现在有多种数据了,ViewHolder自然不能写成某一种,而是需要写成RecyclerView.ViewHolder,然后同样让所有类型的ViewHolder的继承RecyclerView.ViewHolder。
然后我需要三种类型的ViewHolder,分别是视频,文本,图片,所以首先创建三个标识符:
接着在getItemViewType中分别给从网络返回的type数据赋值:
然后为每种类型创建对应的ViewHolder:
可以从最上面的最终效果看到,每一种布局都有相同的部分,把这一部分的实例写在同一个类中,然后初始化布局写在同一个方法中,比如下面这样:
接着非常简单的,在之前创建的各类型对应的ViewHolder把这些公共部分添加进去,同时初始化该类型特有的控件:
初始化布局基本上就完成了,接下来就是要把从网络获取的数据放到布局上,首先还是关于公共部分的数据获取,把所有公共视图的数据获取放在一个方法中,也可以避免很多重复的代码,比如:
之后就是剩下的各类ViewHolder中的数据获取了,在onBindViewHolder方法中:
需要注意到,上面节操播放器的用法,setUp这个方法接受三个参数,第一个是视频地址,第二个一种播放窗口的模式,第三个是视频的标题,没有就填”“,不能填null,不然会报错,节操播放器的控件在布局中差不多是这么用:
最后是RecyclerView适配器的完整代码,关于布局的代码就不写了,因为非常非常多~~~:
PhotoView+Glide+Dialog+ViewPager:打造轻量级的图片浏览方案
http://www.jianshu.com/p/629300228921
我照着文章做了一个结合PhotoView显示长图的Dialog,首先自定义Dialog的显示效果,在style中添加:
然后自定义Dialog的布局文件:
接着是自定义创建一个Config类,用于设置Dialog的宽和高:
接下来开始自定义Dialog:
最后在TypesNewsRecyclerAdapter的onBindViewHolder方法中添加:
看一下效果吧!
可以看到,整个列表中,有视频布局,纯文本的笑话布局,长图片布局,动态图片布局;最后两个可以合并在一个布局里去展示。
所以首先,要显示上面的东西需要用到下面这些控件:
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(); } }); } } }
看一下效果吧!
相关文章推荐
- RecyclerView加载不同类型的布局
- Android Studio 使用RecyclerView加载不同样式布局
- Android RecyclerView 加载更多数据 及 不同类型itemView的使用
- Android RecyclerView加载不同布局简单实现
- CoordinatorLayout +RecyclerView+加载不同布局的item
- Android使用OKHTTP网络框架请求数据,RecyclerView结合Glide展示图片,瀑布流布局样式
- RecyclerView支持下拉刷新上划加载,多种布局样式。RV集成框架使用(一)
- XrecyclerView加载数据+切换不同布局
- RecyclerView的简单使用(不同类型的view以及header、footer)
- 使用RecycleView加载不同的布局(类似淘宝京东购物车+推荐商品列表)
- RecyclerView点击事件、加载不同布局
- 使用RecyclerView实现两种不同Item布局
- CoordinatorLayout +RecyclerView+加载不同布局的item
- Android Listview加载不同布局,ViewHolder类型转换异常!!!
- Android Listview加载不同布局,ViewHolder类型转换异常!!!
- [置顶] RecyclerView实现加载多种条目类型,仿新闻列表多种item布局.
- Android Listview加载不同布局,ViewHolder类型转换异常!!!
- 安卓RecyclerView高阶使用详解(多套布局,加载更多,监听)
- RecyclerView 实现多种布局(上半部Gridview样式,下半部Listview样式)以及多种数据类型实现不同布局
- 优雅的使用RecyclerView(在一个recyclerView里显示有不同子布局的界面,就是混合不同布局)