Exoplayer+Exomedia打造自定义播放器(二)

来源:互联网 发布:程序员用什么画流程图 编辑:程序博客网 时间:2024/05/28 17:06
  • Exomedia源码分析

    VideoControls 播放器基类

    继承自RelativeLayout,播放器基类。作用是提供一些默认的播放器基本组件;提供反射控制器布局、显示加载进度、播放器隐藏显示动画等方法;设置监听回调等等;

    • 基类只提供abstract方法,由子类具体实现。
    public abstract class VideoControls extends RelativeLayout {    //默认的视频播放器组件    protected TextView currentTimeTextView;    protected TextView endTimeTextView;    protected TextView titleTextView;    protected TextView subTitleTextView;    protected TextView descriptionTextView;    ...        /**     * 反射默认播放组件(开始/暂停按钮,快进后退,进度条等)     */    protected void retrieveViews() {        currentTimeTextView = (TextView) findViewById(R.id.exomedia_controls_current_time);        endTimeTextView = (TextView) findViewById(R.id.exomedia_controls_end_time);        titleTextView = (TextView) findViewById(R.id.exomedia_controls_title);        subTitleTextView = (TextView) findViewById(R.id.exomedia_controls_sub_title);        descriptionTextView = (TextView) findViewById(R.id.exomedia_controls_description);    }    ...        //设置进度条    public abstract void setPosition(@IntRange(from = 0) long position);    //设置总时长    public abstract void setDuration(@IntRange(from = 0) long duration);    //更新进度    public abstract void updateProgress(@IntRange(from = 0) long position, @IntRange(from = 0) long duration, @IntRange(from = 0, to = 100) int bufferPercent);    //反射播放控制器总体布局    @LayoutRes    protected abstract int getLayoutResource();    ...    }

    VideoControlsMobile 默认播放器

    布局文件


    1. exomedia_default_controls_mobile.xml
    2. 布局分为三部分:上方视频信息框,中间加载进度框,下方控制器(对应id:exomedia_controls_text_container/exomedia_controls_video_loading/exomedia_controls_interactive_container)
    3. 默认播放器中视频信息框设置为不显示.
    Java

    继承VideoControls类,具体实现父类的虚拟方法.

    public class VideoControlsMobile extends VideoControls {    //进度条    protected SeekBar seekBar;        //用户手动拖拽进度条    protected boolean userInteracting = false;        //反射布局    @Override    protected int getLayoutResource() {        return R.layout.exomedia_default_controls_mobile;    }        @Override    public void setPosition(@IntRange(from = 0L) long position) {        //继承自VideoView : 当前视频时间        currentTimeTextView.setText(TimeFormatUtil.formatMs(position));        seekBar.setProgress((int) position);    }    @Override    public void setDuration(@IntRange(from = 0L) long duration) {        if (duration != seekBar.getMax()) {            //继承自VideoView : 视频长度            endTimeTextView.setText(TimeFormatUtil.formatMs(duration));            seekBar.setMax((int) duration);        }    }    @Override    public void updateProgress(@IntRange(from = 0L) long position, @IntRange(from = 0L) long duration, @IntRange(from = 0L, to = 100L) int bufferPercent) {        if (!userInteracting) {            //设置seekbar的缓冲进度和真实进度的关系            seekBar.setSecondaryProgress((int) (seekBar.getMax() * ((float) bufferPercent / 100)));            seekBar.setProgress((int) position);            currentTimeTextView.setText(TimeFormatUtil.formatMs(position));        }    }    ...}

    具体实现自行参考源码,这里不再赘述。

    自定义播放器

    Exomedia作为模块导入

    github下载zip文件,把其中的library作为module导入工程即可.

    布局文件

    1. 复制默认播放器布局文件exomedia_default_controls_mobile.xml文件并重命名.
    2. 由于继承VideoControls类,基类中已经设置了对默认布局文件的引用,故不要删除已经存在的代码:不需要的按钮只需设置android:visibility="gone",要改变控件样式把原来id赋给新的控件即可。 具体代码请根据个人需求自行编写,下面举例说明:
    <!--设置视频文字信息不可见--><LinearLayout        android:id="@+id/exomedia_controls_text_container"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentTop="true"        android:background="@drawable/exomedia_default_controls_text_background"        android:orientation="vertical"        android:paddingBottom="16dp"        android:paddingLeft="16dp"        android:paddingRight="16dp"        android:paddingTop="16dp"        android:visibility="gone">        <TextView            android:id="@+id/exomedia_controls_title"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:textColor="@android:color/white"            android:textSize="16sp"            android:textStyle="bold"            tools:text="The Video Title"/>            ...    </LinearLayout><!--播放按钮位置调整,改变样式-->    <RelativeLayout        android:id="@+id/exomedia_controls_play_pause_btn_container"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:background="@drawable/shape_circle_enable_pausebtn">        <!--id不变-->        <ImageButton            android:id="@+id/exomedia_controls_play_pause_btn"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:background="@android:color/transparent"            android:minHeight="@dimen/exomedia_min_button_height"            android:minWidth="@dimen/exomedia_min_button_height"            app:srcCompat="@drawable/exomedia_ic_play_arrow_white"            tools:ignore="ContentDescription"/>    </RelativeLayout>
    • 背景黑色为了方便设计,真正使用时请去掉,否则会遮挡住视频播放。

    Java

    1. 与默认播放器的实现方法一样,自定义MyVideoControls extends VideoControls,并让该类反射自定义的布局文件实现定制播放器的效果。
    2. 如果在自定义的布局文件中添加了控件,在此对其业务逻辑进行处理。
    public class MyVideoControlsMobile extends VideoControls {    //自己添加的开始/暂停按钮的容器    protected RelativeLayout pauseBtnContainer;    //反射自己的布局    @Override    protected int getLayoutResource() {        return R.layout.my_exomedia_controls_mobile;    }        @Override    protected void animateVisibility(boolean toVisible) {        if (isVisible == toVisible) {            return;        }        if (!hideEmptyTextContainer || !isTextContainerEmpty()) {            textContainer.startAnimation(new TopViewHideShowAnimation(textContainer, toVisible, CONTROL_VISIBILITY_ANIMATION_LENGTH));        }        if (!isLoading) {            controlsContainer.startAnimation(new BottomViewHideShowAnimation(controlsContainer, toVisible, CONTROL_VISIBILITY_ANIMATION_LENGTH));        }        //设置自定义的开始/暂停按钮的可见性        if (toVisible) {            pauseBtnContainer.setVisibility(View.VISIBLE);        } else {            pauseBtnContainer.setVisibility(View.GONE);        }        isVisible = toVisible;        onVisibilityChanged();    }    @Override    public void showLoading(boolean initialLoad) {        if (isLoading) {            return;        }        isLoading = true;        loadingProgressBar.setVisibility(View.VISIBLE);        if (initialLoad) {            controlsContainer.setVisibility(View.GONE);            //控制器不可见时,开始/暂停按钮也不可见            pauseBtnContainer.setVisibility(View.GONE);        } else {            //按钮不可以点击            pauseBtnContainer.setBackgroundResource(R.drawable.shape_circle_disable_pausebtn);            playPauseButton.setEnabled(false);            previousButton.setEnabled(false);            nextButton.setEnabled(false);            return;        }        show();    }        @Override    public void finishLoading() {        if (!isLoading) {            return;        }        isLoading = false;        loadingProgressBar.setVisibility(View.GONE);        //控制器可见时,开始/暂停按钮也可见        pauseBtnContainer.setVisibility(View.VISIBLE);        controlsContainer.setVisibility(View.VISIBLE);        playPauseButton.setEnabled(true);        previousButton.setEnabled(enabledViews.get(com.devbrackets.android.exomedia.R.id.exomedia_controls_previous_btn, true));        nextButton.setEnabled(enabledViews.get(com.devbrackets.android.exomedia.R.id.exomedia_controls_next_btn, true));        pauseBtnContainer.setBackgroundResource(R.drawable.shape_circle_enable_pausebtn);        updatePlaybackState(videoView != null && videoView.isPlaying());    }    }

    在此仅说明了定制播放器的流程,代码请根据具体业务需求自行实现。

    深度定制

    把Exomedia作为模组导入以后,直接修改与VideoControls相关的类和xml,以实现更加灵活、扩展性更好的自定义播放器。

    其他

    相关文章请点击下面链接:

    • Exoplayer+Exomedia打造自定义播放器(一)
    • Exoplayer+Exomedia之玩转视频播放事件监听

阅读全文
1 0
原创粉丝点击