上一节对欢迎模块进行了综述(可参见 8. 视频模块 进行了解),接下来将从视频模块开始详细介绍:
- 视频模块(一)之统计
- [视频模块(二)之统计详情]
知识点
- 掌握“视频列表”界面的开发
- 实现下拉刷新功能
主要功能:
- 展示各学科经典视频,点击条目中的视频会进入对应的“视频”详情界面;
- 在该节目可以播放视频、展示视频简介与视频目录;
- 调整播放画面的尺寸和视频清晰度等。
视频列表
任务综述:
“视频列表”界面主要展示各学科的视频信息,该列表的数据从Tomcat服务器上获取,然后经过JSON解析把数据显示到“视频列表”界面上。
1. “视频列表”界面
任务分析:
“视频列表”界面主要用于展示各学科的视频信息,“视频列表”界面的效果如图所示。
任务实施:
(1)创建“视频列表”界面:fragment_video.xml。
(2)放置界面控件。在布局文件中,放置一个PullToRefreshView控件用于显示下拉刷新,一个WrapRecyclerView控件用于加载视频列表信息。
fragment_video.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.itheima.PullToRefreshView
android:id="@+id/pull_to_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f6f6f6">
<com.itheima.topline.view.WrapRecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@null"
android:dividerHeight="0dp"
android:fadingEdge="none" />
</com.itheima.PullToRefreshView>
</LinearLayout>
2. “视频列表”界面Item
任务分析:
由于“视频列表”界面用到了WrapRecyclerView控件,因此需要为该控件创建一个Item界面,界面效果如图所示。
任务实施
(1)创建“视频列表”界面Item:video_list_item.xml。
(2)导入界面图片(1个,media_play_icon.png)。
(3)放置界面控件。
2个ImageView控件分别用于显示视频图片和视频播放图标。
video_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp">
<ImageView
android:id="@+id/iv_img_round"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitXY" />
<ImageView
android:id="@+id/iv_media_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/media_play_icon" />
</RelativeLayout>
3. 创建VideoBean
任务分析:
由于每个学科的视频信息都有视频Id、视频名称、视频简介、视频图片等属性,因此需要创建一个VideoBean类存放这些属性。
VideoBean.java
public class VideoBean {
private int id; //视频id
private String name; //视频名称
private String intro; //视频简介
private String img; //视频图片
private List<VideoDetailBean> videoDetailList; //视频详情中的列表
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIntro() {
return intro;
}
public void setIntro(String intro) {
this.intro = intro;
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
public List<VideoDetailBean> getVideoDetailList() {
return videoDetailList;
}
public void setVideoDetailList(List<VideoDetailBean> videoDetailList) {
this.videoDetailList = videoDetailList;
}
}
(2)创建VideoDetailBean类。由于“视频详情”界面中有一个拥有自己的视频Id与视频名称等属性的视频目录列表,因此需要在bean包中创建一个VideoDetailBean类,在该类中存放视频详情中视频目录的属性。
VideoDetailBean.java
public class VideoDetailBean implements Serializable {
private static final long serialVersionUID = 1L;
private String video_id;
private String video_name;
public String getVideo_id() {
return video_id;
}
public void setVideo_id(String video_id) {
this.video_id = video_id;
}
public String getVideo_name() {
return video_name;
}
public void setVideo_name(String video_name) {
this.video_name = video_name;
}
}
4.“视频列表”界面Adapter
任务分析:
“视频列表”界面是用WrapRecyclerView控件展示视频信息的,因此需要创建一个数据适配器VideoListAdapter对WrapRecyclerView控件进行数据适配。
任务实施:
(1)创建VideoListAdapter类。在adapter包中创建一个VideoListAdapter类继承RecyclerView.Adapter<RecyclerView.ViewHolder>,并重写onCreateViewHolder()、onBindViewHolder()、getItemCount()方法。
(2)创建ViewHolder()方法。在ViewHolderAdapter类中创建一个ViewHolder类以获取Item界面上的控件。
VideoListAdapter.java
public class VideoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
{
private List<VideoBean> videoList;
private Context context;
public VideoListAdapter(Context context) {
this.context = context;
}
public void setData(List<VideoBean> videoList) {
this.videoList = videoList;
notifyDataSetChanged();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int
viewType)
{
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.
layout.video_list_item, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int i) {
final VideoBean bean = videoList.get(i);
Glide
.with(context)
.load(bean.getImg())
.error(R.mipmap.ic_launcher)
.into(((ViewHolder) holder).iv_img);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(context, VideoDetailActivity.class);
intent.putExtra("intro", bean.getIntro());
intent.putExtra("videoDetailList", (Serializable) bean.getVideoDetailList());
context.startActivity(intent);
}
});
}
@Override
public int getItemCount() {
return videoList == null ? 0 : videoList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ImageView iv_img;
public ViewHolder(View itemView) {
super(itemView);
iv_img = (ImageView) itemView.findViewById(R.id.iv_img_round);
}
}
}
5. “视频列表”界面数据
任务分析:
“视频列表”界面由视频数据组成,其中,视频图片通过在Tomacat的ROOT文件夹中创建一个图片文件夹video存放,视频数据通过在ROOT文件夹中创建一个video_list_data.json文件存放。
任务实施:
(1)创建“视频列表”界面图片存放的文件夹。在Tomcat的ROOT/topline/img文件夹中创建一个video文件夹,用于存放视频列表界面图片。
(2)在Tomcat服务器中创建“视频列表”界面数据文件。点击视频列表的每个条目会获取各个条目多对应的视频详情以及相关视频目录列表,由于服务器中的数据是手动添加的,如果将每个视频详情中的视频目录列表数据一个个地添加到服务器,则会产生较多的JSON文件,因此为了减少文件数量,可以在视频列表的JSON文件中存放视频详情中对应的视频目录列表信息。在Tomcat的ROOT/topline目录中创建一个video_list_data.json文件,该文件用于存放视频列表与视频详情中需要加载的数量。
video_list_data.json
[
{
"id":1,
"name":"jQuery精品教程",
"img":"http://172.27.35.1:8080/topline/img/video/video_jquery_icon.png",
"intro":"本视频系统的讲解了jQuery的基本操作并配合相应案例保证学生能较大程度的接受和了解到知识的应用,该视频的起点都是针对有一定JavaScript基础的同学精心设计录制的。通过该视频的学习,相信你能够轻轻松松的掌握jQuery的应用,为学习前端开发打下坚实的基础。",
"videoDetailList":[
{
"video_id":"DA2D015D371417299C33DC5901307461",
"video_name":"01-jQuery初体验"
},
{
"video_id":"8CE6F0EA79D28C409C33DC5901307461",
"video_name":"02-什么是jQuery"
},
{
"video_id":"105420027A12F7869C33DC5901307461",
"video_name":"03-jQuery版本问题"
},
{
"video_id":"2B6B824CB0FB90209C33DC5901307461",
"video_name":"04-jQuery入口函数的解释"
},
{
"video_id":"FE97256B916E64779C33DC5901307461",
"video_name":"05-jq对象与js对象"
}
]
},
……
{
"id":7,
"name":"MFC教程",
"img":"http://172.27.35.1:8080/topline/img/video/video_c_icon.png",
"intro":"第一天(Win消息机制、SDK编程基础)第二天(对话框、常用控件、文档和视图)第三天(综合案例:销售信息管理系统)",
"videoDetailList":[
{
"video_id":"CC64EB602031C45E9C33DC5901307461",
"video_name":"01_mfc课程安排"
},
{
"video_id":"8002DA7F236A263E9C33DC5901307461",
"video_name":"02_底层窗口实现(一)_WinMain入口函数"
},
{
"video_id":"A8959C2D57B521A19C33DC5901307461",
"video_name":"03_底层窗口实现(二)_创建窗口的前五步"
},
{
"video_id":"F0B07D2892DE91C79C33DC5901307461",
"video_name":"04_底层窗口现实(三)_窗口过程处理"
}
]
}
]
(3)在Constant类中添加视频列表接口。由于“视频列表”界面向服务器请求数据需要一个接口地址,因此,在utils包中的Constant类中添加如下代码:
//视频列表接口
public static final String REQUEST_VIDEO_URL = "/video_list_data.json";
(4)解析JSON数据。由于从Tomcat服务器中获取的JSON格式的数据不能直接加载到界面上,因此需要在utils包的JsonParse类中创建一个getVideoList()方法,用于解析该界面获取的JSON数据,需要在JsonParse类中添加如下代码:
public List<VideoBean> getVideoList(String json) {
//使用gson库解析JSON数据
Gson gson = new Gson();
//创建一个TypeToken的匿名子类对象,并调用对象的getType()方法
Type listType = new TypeToken<List<VideoBean>>() {
}.getType();
//把获取到的信息集合存到videoList中
List<VideoBean> videoList = gson.fromJson(json, listType);
return videoList;
}
6. “视频列表”界面逻辑代码
任务分析:
“视频列表”界面主要是一个展示视频信息的列表,该界面中的数据是通过解析Tomcat中的video_list_data.json文件而得到的,然后把解析后的数据加载到“视频列表”界面。
任务实施:
(1)创建VideoFragment类。在fragment包中创建一个VideoFragment类。在该类中创建界面控件的初始化方法initView(),在该方法中获取“视频列表”界面需要用到的UI控件并初始化。
(2)从服务器获取数据。在VideoFragment中创建一个initData()方法,用于从Tomcat服务器中获取视频列表数据。
VideoFragment
public class VideoFragment extends Fragment {
private PullToRefreshView mPullToRefreshView;
private WrapRecyclerView recycleView;
public static final int REFRESH_DELAY = 1000;
public static final int MSG_VIDEO_OK = 1; //获取数据
private MHandler mHandler; //事件捕获
private VideoListAdapter adapter;
public VideoFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mHandler = new MHandler();
initData();
View view = initView(inflater, container);
return view;
}
private View initView(LayoutInflater inflater, ViewGroup container) {
View view = inflater.inflate(R.layout.fragment_video, container, false);
recycleView = (WrapRecyclerView) view.findViewById(R.id.recycler_view);
recycleView.setLayoutManager(new LinearLayoutManager(getContext()));
adapter = new VideoListAdapter(getActivity());
recycleView.setAdapter(adapter);
mPullToRefreshView = (PullToRefreshView) view.findViewById(R.id.
pull_to_refresh);
mPullToRefreshView.setOnRefreshListener(new PullToRefreshView.
OnRefreshListener() {
@Override
public void onRefresh() {
mPullToRefreshView.postDelayed(new Runnable() {
@Override
public void run() {
mPullToRefreshView.setRefreshing(false);
initData();
}
}, REFRESH_DELAY);
}
});
return view;
}
private void initData() {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(Constant.WEB_SITE + Constant.
REQUEST_VIDEO_URL).build();
Call call = okHttpClient.newCall(request);
//开启异步线程访问网络
call.enqueue(new Callback() {
@Override
public void onResponse(Response response) throws IOException {
String res = response.body().string();
Message msg = new Message();
msg.what = MSG_VIDEO_OK;
msg.obj = res;
mHandler.sendMessage(msg);
}
@Override
public void onFailure(Request arg0, IOException arg1) {
}
});
}
/**
* 事件捕获
*/
class MHandler extends Handler {
@Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
switch (msg.what) {
case MSG_VIDEO_OK:
if (msg.obj != null) {
String vlResult = (String) msg.obj;
//使用Gson解析数据
List<VideoBean> videoList = JsonParse.getInstance().
getVideoList(vlResult);
adapter.setData(videoList);
}
break;
}
}
}
}
(3)修改底部导航栏。由于点击底部导航栏的“视频”按钮时会出现“视频列表”界面,因此找到MainActivity.java中的initView()方法,在该方法的“CountFragment countFragment = new CountFragment();”语句下方添加如下代码:
VideoFragment videofragment = new VideoFragment();
在“alFragment.add(countFragment);”语句下方添加如下代码:
alFragment.add(videoFragment);
网友评论