上一节对欢迎模块进行了综述(可参见 8. 统计模块 进行了解),接下来将从视频模块开始详细介绍:
- 视频模块(一)之视频列表
- 视频模块(二)之视频详情1
- [视频模块(二)之视频详情2]
知识点
- 显示视频简介、视频目录、视频播放等信息
- 使用第三方CC视频播放器播放
视频详情1
任务综述:
“视频详情”界面主要显示视频简介、视频目录、视频播放等信息,由于该界面的数据是从“视频列表”界面传递过来的,因此只需要把传递过来的数据展示到界面即可。“视频详情”界面中的视频使用第三方CC视频播放器播放。
7. “视频详情”界面
任务分析:
点击视频列表的条目会跳转到“视频详情”界面,该界面主要显示视频简介,视频目录以及视频播放等信息,界面效果如图所示。
![](https://img.haomeiwen.com/i10186693/b1d260f03957a3f0.png)
![](https://img.haomeiwen.com/i10186693/128c1f0d57b5e3c9.png)
任务实施:
(1)创建“视频详情”界面。在activity包中创建VideoDetailActivity,布局文件名为activity_video_detail。
(2)导入界面图片(13个)。
(3)添加design库。由于“视频详情”界面用到了design库中的TabLayout类,因此需要在该项目中添加design库。在AS中,选中项目,右击选择Open Module Settings/Dependencies/+/Library dependency/com.android.support:design:25.3.1库加入主项目。
(4)放置界面控件。
activity_video_detail.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="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/rl_play"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:background="#000000">
<SurfaceView
android:id="@+id/playerSurfaceView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
<ProgressBar
android:id="@+id/bufferProgressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
<ImageView
android:id="@+id/iv_center_play"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:src="@drawable/big_stop_ic"
android:visibility="gone" />
<LinearLayout
android:id="@+id/playerTopLayout"
android:layout_width="fill_parent"
android:layout_height="45dp"
android:layout_alignParentTop="true"
android:layout_gravity="top"
android:background="@drawable/play_top_bg"
android:orientation="horizontal"
android:padding="3dp"
android:visibility="gone">
<ImageView
android:id="@+id/backPlayList"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@drawable/back" />
<TextView
android:id="@+id/videoIdText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:gravity="left"
android:singleLine="true"
android:textColor="#FFFFFFFF"
android:textSize="16sp" />
<ImageView
android:id="@+id/iv_top_menu"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="15dp"
android:layout_marginRight="20dp"
android:padding="5dp"
android:scaleType="fitXY"
android:src="@drawable/more_ic" />
</LinearLayout>
<LinearLayout
android:id="@+id/playerBottomLayout"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:background="#B2000000"
android:orientation="horizontal"
android:visibility="gone">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_video_back"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:src="@drawable/up_ic" />
<ImageView
android:id="@+id/iv_play"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:src="@drawable/smallstop_ic" />
<ImageView
android:id="@+id/iv_video_next"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:src="@drawable/down_ic" />
</LinearLayout>
<TextView
android:id="@+id/playDuration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="5dp"
android:textColor="#FFFFFF" />
<SeekBar
android:id="@+id/skbProgress"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:maxHeight="3dp"
android:minHeight="3dp"
android:progressDrawable="@drawable/seekbar_style"/>
<TextView
android:id="@+id/videoDuration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="8dp"
android:textColor="#FFFFFF" />
<ImageView
android:id="@+id/iv_fullscreen"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/fullscreen_close" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center"
android:orientation="horizontal">
<!-- 倍速播放选择 -->
<TextView
android:id="@+id/tv_speed_play"
style="@style/playBottomTextViewStyle"
android:text="@string/speed" />
<TextView
android:id="@+id/tv_definition"
style="@style/playBottomTextViewStyle"
android:text="@string/definition" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/volumeLayout"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="30dp"
android:background="#80000000"
android:gravity="center_horizontal"
android:orientation="vertical"
android:visibility="gone">
<com.itheima.topline.view.VerticalSeekBar
android:id="@+id/volumeSeekBar"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:maxHeight="5dp"
android:minHeight="5dp"
android:progressDrawable="@drawable/seekbar_style" />
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginBottom="10dp"
android:src="@drawable/volume" />
</LinearLayout>
<ImageView
android:id="@+id/iv_lock"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:padding="5dp"
android:scaleType="fitCenter"
android:src="@drawable/player_lock_bg"
android:visibility="gone" />
</RelativeLayout>
<LinearLayout
android:id="@+id/ll_below_info"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="3"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
app:tabIndicatorColor="@android:color/holo_red_dark"
app:tabSelectedTextColor="@android:color/holo_red_dark"
app:tabTextColor="@android:color/black" />
<!--可滑动的布局内容-->
<android.support.v4.view.ViewPager
android:id="@+id/vp_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
(5)创建play_top_bg.xml文件。“视频详情”界面需要一个渐变背景。
play_top_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<gradient android:startColor="#CC000000" android:endColor="#00000000"
android:angle="270"/>
</shape>
上述代码中,用于定义形状,gradient用于定义该形状为渐变色填充,startColor为起始颜色,endColor为结束颜色,angle表示渐变角度,且必须是45的整数倍。
(6)修改strings.xml文件。
<string name="definition">清晰度</string>
<string name="speed">倍速</string>
(7)创建播放条SeekBar的样式。由于播放视频时的播放条具有一定的样式,因此需要res/drawable文件夹中创建一个seekbar_style.xml文件,用于设置播放条的样式。
seekbar_style.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="10dip" />
<gradient
android:angle="270"
android:centerColor="#151515"
android:centerY="0.45"
android:endColor="#151515"
android:startColor="#151515" />
</shape>
</item>
<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="10dip" />
<gradient
android:angle="270"
android:centerColor="#333333"
android:centerY="0.45"
android:endColor="#333333"
android:startColor="#333333" />
</shape>
</clip>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="10dip" />
<gradient
android:angle="270"
android:centerColor="#a07e5d"
android:centerY="0.45"
android:endColor="#a07e5d"
android:startColor="#a07e5d" />
</shape>
</clip>
</item>
</layer-list>
(8)创建清晰度播放选择的文本样式。由于在横屏播放视频时有选择清晰度的文本,这些文本都使用相同的样式,因此需要在res/values文件夹的styles.xml文件中添加名为playBottomTextStyle的样式。
<style name="playBottomTextViewStyle" parent="android:Widget.Holo.Light.TextView">
<item name="android:layout_marginRight">5dp</item>
<item name="android:textColor">#FFFFFF</item>
<item name="android:textSize">13sp</item>
<item name="android:visibility">gone</item>
<item name="android:padding">5dp</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_gravity">center_vertical</item>
</style>
(9)创建视频的锁屏图标。由于在横屏播放时有锁屏图标,当点击锁屏时,会显示一个上锁的图标(lock_ic.png),当再次点击开锁时,会显示一个开锁的图标(unlock_ic.png),因此为了实现这个效果,需要在res/drawable文件夹中创建一个player_lock_bg.xml文件。
player_lock_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/lock_ic" android:state_selected="true" />
<item android:drawable="@drawable/unlock_ic" android:state_selected="false" />
</selector>
(10)创建视频简介布局和视频目录布局。由于“视频详情”界面还包含一个视频简介与一个视频目录,因此需要在res/layout文件夹中创建video_detail_viewpager1.xml文件与video_detail_viewpager2.xml文件,分别用于显示视频简介布局与视频目录布局。
video_detail_viewpager1.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">
<TextView
android:id="@+id/tv_intro"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="8dp"
android:lineSpacingExtra="4dp"
android:paddingLeft="8dp"
android:paddingRight="8dp" />
</LinearLayout>
video_detail_viewpager2.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">
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#e1e1e1" />
<ListView
android:id="@+id/lv_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
8. “视频目录”列表Item
任务分析:
由于“视频详情”界面的视频目录用到了Listview控件,因此需要为该控件创建一个Item布局,界面效果如图所示。
![](https://img.haomeiwen.com/i10186693/9a9335621bbe62f4.png)
任务实施:
(1)创建“视频目录”列表Item:video_detail_item.xml。
(2)导入界面图片(2个)。
(3)放置界面控件。
一个TextView控件用于显示视频名称;
一个ImageView控件用于显示播放图标。
video_detail_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="match_parent"
android:padding="10dp">
<TextView
android:id="@+id/tv_video_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true" />
<ImageView
android:id="@+id/iv_icon"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:scaleType="fitXY"
android:src="@drawable/iv_video_icon" />
</RelativeLayout>
9. 画面尺寸菜单
任务分析:
在“视频详情”界面点击正在播放的视频右下角的“全屏”图标,界面会变成横屏显示,当点击“视频”界面右上角的“更多”按钮时,会弹出画面尺寸选择的菜单。
任务实施:
(1)创建“画面尺寸菜单”画面:play_top_menu.xml。
(2)放置界面控件。
一个TextView控件用于显示“画面尺寸”文字;
4个RadioButton控件分别用于显示满屏、100%、75%、以及50%四个按钮。
play_top_menu.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"
android:paddingLeft="15dp"
android:paddingTop="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="5dp"
android:layout_marginTop="15dp"
android:text="画面尺寸:"
android:textColor="#FFFFFF"
android:textSize="14sp" />
<RadioGroup
android:id="@+id/rg_screensize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_screensize_full"
style="@style/rbStyle"
android:text="满屏" />
<RadioButton
android:id="@+id/rb_screensize_100"
style="@style/rbStyle"
android:layout_marginLeft="10dp"
android:checked="true"
android:text="100%" />
<RadioButton
android:id="@+id/rb_screensize_75"
style="@style/rbStyle"
android:layout_marginLeft="10dp"
android:text="75%" />
<RadioButton
android:id="@+id/rb_screensize_50"
style="@style/rbStyle"
android:layout_marginLeft="10dp"
android:text="50%" />
</RadioGroup>
</LinearLayout>
(3)修改styles.xml文件。由于在画“面尺寸菜单”界面中的满屏、100%、75%以及50%这4个按钮的样式是相同的,因此需要在res/values文件夹的styles.xml文件中添加一个名为rbStyle的样式。
<style name="rbStyle">
<item name="android:button">@null</item>
<item name="android:padding">5dp</item>
<item name="android:textColor">@drawable/play_rb_textcolor</item>
<item name="android:textSize">12sp</item>
</style>
(4)创建play_rb_textcolor.xml文件。由于画“面尺寸菜单”界面中的4个按钮在点击后字体颜色会发生变化,以“满屏”按钮为例,当未点击“满屏”按钮时,按钮上的文字为白色;当点击“满屏”按钮时,按钮上的文字为橙色,因此需要在res/drawable文件夹中创建一个play_rb_textcolor.xml文件(文字颜色选择器)。
play_rb_textcolor.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="@color/rb_text_check" />
<item android:color="@android:color/white" android:state_checked="false" />
</selector>
(5)修改colors.xml文件。play_rb_textcolor.xml文件用到了rb_text_check颜色值。
<color name="rb_text_check">#ff5200</color>
10. “视频目录”列表Adapter
任务分析:
“视频目录”列表是通过ListView控件展示视频目录信息,因此需要创建一个数据适配器VideoDetailListAdapter对ListView控件进行数据适配。
任务实施:
(1)创建VideoDetailListAdapter类。在adapter包中创建一个VideoDetailListAdapter类继承BaseAdapter类,并重写getCount()、getItem()、getItemId()、getView()方法。在getView()方法中设置XML布局、数据以及界面跳转方法,同时,为了减少缓存,需要复用convertView对象。
VideoDetailListAdapter.java
public class VideoDetailListAdapter extends BaseAdapter {
private Context mContext;
private List<VideoDetailBean> vdbl;
private int selectedPosition = -1;//点击时选中的位置
private OnSelectListener onSelectListener;
public VideoDetailListAdapter(Context context, OnSelectListener onSelectListener) {
this.mContext = context;
this.onSelectListener = onSelectListener;
}
public void setSelectedPosition(int position) {
selectedPosition = position;
}
/**
* 设置数据 更新界面
*/
public void setData(List<VideoDetailBean> vdbl) {
this.vdbl = vdbl;
notifyDataSetChanged();
}
/**
* 获取Item的总数
*/
@Override
public int getCount() {
return vdbl == null ? 0 : vdbl.size();
}
/**
* 根据position得到对应Item的对象
*/
@Override
public VideoDetailBean getItem(int position) {
return vdbl == null ? null : vdbl.get(position);
}
/**
* 根据position得到对应Item的id
*/
@Override
public long getItemId(int position) {
return position;
}
/**
* 得到相应position对应的Item视图,参数position是当前Item的位置,
* 参数convertView就是滑出屏幕的Item的View
*/
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder vh;
//复用convertView
if (convertView == null) {
vh = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(
R.layout.video_detail_item, null);
vh.title = (TextView) convertView.findViewById(R.id.tv_video_name);
vh.iv_icon = (ImageView) convertView.findViewById(R.id.iv_icon);
convertView.setTag(vh);
} else {
vh = (ViewHolder) convertView.getTag();
}
//获取position对应的Item的数据对象
final VideoDetailBean bean = getItem(position);
vh.title.setTextColor(mContext.getResources().getColor(R.color.
video_detail_text_color));
if (bean != null) {
vh.title.setText(bean.getVideo_name());
//设置选中效果
if (selectedPosition == position) {
vh.iv_icon.setImageResource(R.drawable.iv_video_selected_icon);
vh.title.setTextColor(mContext.getResources().getColor(R.color.
rdTextColorPress));
} else {
vh.iv_icon.setImageResource(R.drawable.iv_video_icon);
vh.title.setTextColor(mContext.getResources().getColor(R.color.
video_detail_text_color));
}
}
//每个Item的点击事件
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//跳转到习题详情界面
if (bean == null) {
return;
}
//播放视频
onSelectListener.onSelect(position, vh.iv_icon);
}
});
return convertView;
}
class ViewHolder {
public TextView title;
public ImageView iv_icon;
}
/**
* 创建OnSelectListener接口把位置position和控件ImageView传递到Activity界面
*/
public interface OnSelectListener {
void onSelect(int position, ImageView iv);
}
}
(2)修改colors.xml文件。由于视频目录标题多次使用同一颜色值,因此为了减少代码量与方便调用,需要把视频目录文本的颜色值添加到res/values文件夹中的colors.xml文件中。
<color name="video_detail_text_color">#333333</color>
11. 创建NewsDemoApplication
任务分析:
由于“视频播放”界面用到了第三方CC视频播放器,同时在播放视频之前需要启动服务,因此在该项目中需要创建一个Application用于处理CC视频播放器用到的服务。
任务实施:
(1)添加CCSDK.jar库。由于视频播放调用是第三方CC视频播放器,因此需要在Project选项卡下将CCSDK.jar复制到app中的libs文件夹,选择CCSDK.jar库/右击选择Add As Library选项/弹出一个对话框/把该jar包放在app项目中即可。
(2)创建NewsDemoApplication.java文件。由于CC视频播放器在播放视频时需要开启DRMServer服务。因此需要在com.XXXX.newsdemo文件夹中创建一个NewsDemoApplication类,用于设置视频播放时用到的服务。
NewsDemoApplication.java
public class NewsDemoApplication extends Application {
private DRMServer drmServer;//视频播放时用到的服务
@Override
public void onCreate() {
startDRMServer();
super.onCreate();
}
//启动DRMServer
public void startDRMServer() {
if (drmServer == null) {
drmServer = new DRMServer();
drmServer.setRequestRetryCount(10);
}
try {
drmServer.start();
setDrmServerPort(drmServer.getPort());
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "启动解密服务失败,请检查网络限制情况",
Toast.LENGTH_LONG).show();
}
}
@Override
public void onTerminate() {
if (drmServer != null) {
drmServer.stop();
}
super.onTerminate();
}
private int drmServerPort;
public int getDrmServerPort() {
return drmServerPort;
}
public void setDrmServerPort(int drmServerPort) {
this.drmServerPort = drmServerPort;
}
public DRMServer getDRMServer() {
return drmServer;
}
}
(3)修改清单文件。在AndroidManifest.xml文件中需要设置application标签中的name属性值为“.NewsDemoApplication”。
12. 创建VideoDetailPagerAdapter
任务分许:
由于“视频详情”界面用到了ViewPager控件,因此需要创建一个VideoDetailPagerAdapter对ViewPager控件进行数据填充。
任务实施:
在adapter文件夹中创建一个VideoDetailPagerAdapter类并继承PagerAdapter类。
VideoDetailPagerAdapter.java
public class VideoDetailPagerAdapter extends PagerAdapter {
private List<View> mViewList;
private List<String> mTitleList;
public VideoDetailPagerAdapter(List<View> mViewList, List<String> mTitleList) {
this.mViewList = mViewList;
this.mTitleList=mTitleList;
}
@Override
public int getCount() {
return mViewList.size();//页卡数
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;//官方推荐写法
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(mViewList.get(position));//添加页卡
return mViewList.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(mViewList.get(position));//删除页卡
}
@Override
public CharSequence getPageTitle(int position) {
return mTitleList.get(position);//页卡标题
}
}
13. 创建ParamsUtils
任务分析:
由于在“视频详情”界面中需要把时间转换成字符串显示到界面上,并且还需要把dp转换成px,因此需要创建一个工具类,并在该类中分别创建两个方法实现这些功能。
任务实施:
在utils包中创建一个ParamsUtils类,在该类中创建millsecondsToStr()方法与dpToPx()方法,分别用于把时间转换成字符串,以及把dp转换成px。
ParamsUtils.java
public class ParamsUtils {
public final static int INVALID = -1;
public static int getInt(String str){
int num = INVALID;
try {
num = Integer.parseInt(str);
} catch (NumberFormatException e) {
}
return num;
}
public static String millsecondsToStr(int seconds){ //把时间转换成字符串
seconds = seconds / 1000;
String result = "";
int hour = 0, min = 0, second = 0;
hour = seconds / 3600;
min = (seconds - hour * 3600) / 60;
second = seconds - hour * 3600 - min * 60;
if (hour < 10) {
result += "0" + hour + ":";
} else {
result += hour + ":";
}
if (min < 10) {
result += "0" + min + ":";
} else {
result += min + ":";
}
if (second < 10) {
result += "0" + second;
} else {
result += second;
}
return result;
}
public static int dpToPx(Context context, int height){ //dp转换成px
float density = context.getResources().getDisplayMetrics().density;
height = (int) (height * density + 0.5f);
return height;
}
}
14. 视频播放进度条
任务分析:
由于在“视频详情”界面播放视频时会显示视频播放的进度,因此需要创建一个视频播放的进度条。
任务实施:
在view文件夹中创建一个VerticalSeekBar类用于设置视频播放时的进度条。
VerticalSeekBar.java
public class VerticalSeekBar extends SeekBar {
public VerticalSeekBar(Context context) {
super(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas c) {
c.rotate(-90);
c.translate(-getHeight(), 0);
super.onDraw(c);
}
@Override
public synchronized void setProgress(int progress) {
super.setProgress(progress);
onSizeChanged(getWidth(), getHeight(), 0, 0);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
setProgress((int) ((int) getMax() - (getMax() * event.getY() /
getHeight())));
break;
default:
return super.onTouchEvent(event);
}
return true;
}
}
15. 画面尺寸菜单逻辑代码
任务分析:
当横屏播放视频时,点击屏蔽右上角的“更多”图标会弹出一个选择画面尺寸的菜单,画面尺寸菜单中的选项有满屏、100%、75%以及50%,点击其中任意一项就会使播放界面缩小或放大。
任务实施:
(1)创建PlayTopPopupWindow类。在view文件夹中创建一个PlayTopPopupWindow类,在该类中创建一个setScreenSizeCheckLister()方法,用于监听“选择画面尺寸”界面中按钮的点击事件。
(2)设置画面尺寸菜单。在PlayTopPopupWindow类中创建一个showAsDropDown()方法,用于设置画面尺寸菜单的显示。
PlayTopPopupWindow.java
/**
* 弹出菜单
*/
public class PlayTopPopupWindow {
private PopupWindow popupWindow;
private RadioGroup rgScreenSize;
public PlayTopPopupWindow(Context context, int height) {
View view = LayoutInflater.from(context).inflate(R.layout.play_top_menu, null);
rgScreenSize = findById(R.id.rg_screensize, view);
popupWindow = new PopupWindow(view, height * 2 / 3, height);
popupWindow.setBackgroundDrawable(new ColorDrawable(Color.argb(178, 0, 0, 0)));
}
public void setScreenSizeCheckLister(RadioGroup.OnCheckedChangeListener listener) {
rgScreenSize.setOnCheckedChangeListener(listener);
}
public void showAsDropDown(View parent) {
popupWindow.showAtLocation(parent, Gravity.RIGHT, 0, 0);
popupWindow.setFocusable(true);
popupWindow.setOutsideTouchable(true);
popupWindow.update();
}
public void dismiss() {
popupWindow.dismiss();
}
@SuppressWarnings("unchecked")
private <T extends View> T findById(int resId, View view) {
return (T) view.findViewById(resId);
}
}
网友评论