美文网首页程序员Android开发Android开发经验谈
11. 视频模块(二)之视频详情1

11. 视频模块(二)之视频详情1

作者: Jennyni1122 | 来源:发表于2018-12-17 11:51 被阅读12次

    上一节对欢迎模块进行了综述(可参见 8. 统计模块 进行了解),接下来将从视频模块开始详细介绍:

    知识点

    • 显示视频简介、视频目录、视频播放等信息
    • 使用第三方CC视频播放器播放

    视频详情1

    任务综述:
    “视频详情”界面主要显示视频简介、视频目录、视频播放等信息,由于该界面的数据是从“视频列表”界面传递过来的,因此只需要把传递过来的数据展示到界面即可。“视频详情”界面中的视频使用第三方CC视频播放器播放。

    7. “视频详情”界面

    任务分析:
    点击视频列表的条目会跳转到“视频详情”界面,该界面主要显示视频简介,视频目录以及视频播放等信息,界面效果如图所示。

    “视频详情”界面1 “视频详情”界面2

    任务实施:
    (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布局,界面效果如图所示。

    “视频目录”列表的Item

    任务实施:
    (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);
        }
    }
    

    相关文章

      网友评论

        本文标题:11. 视频模块(二)之视频详情1

        本文链接:https://www.haomeiwen.com/subject/ujaccqtx.html