继承自RelativeLayout,播放器基类。作用是提供一些默认的播放器基本组件;提供反射控制器布局、显示加载进度、播放器隐藏显示动画等方法;设置监听回调等等;
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();
...
}
exomedia_controls_text_container/exomedia_controls_video_loading/exomedia_controls_interactive_container
)继承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));
}
}
...
}
具体实现自行参考源码,这里不再赘述。
github下载zip文件,把其中的library作为module导入工程即可.
exomedia_default_controls_mobile.xml
文件并重命名.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">
<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>
MyVideoControls extends VideoControls
,并让该类反射自定义的布局文件实现定制播放器的效果。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,以实现更加灵活、扩展性更好的自定义播放器。
相关文章请点击下面链接: