I believe that those who do Android development have generally done playing web videos. Everyone generally uses VideoView to play web videos. There is also a Controller to control the pause or fast forward of the video. But the style of Controller cannot be changed to be particularly ugly. Can't meet the high-end UI experience.
Complete a custom playback controller, and a simple horizontal and vertical screen switching function. Probably record the process:
1. Customize MyVideoView, in order to solve the problem that may not cover the entire screen and cause blank edges.
public class MyVideoView extends VideoView {
public MyVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getDefaultSize(0,widthMeasureSpec);
int height = getDefaultSize(0,heightMeasureSpec);
setMeasuredDimension(width,height);
}
}
2. Put VideoView and Controller into an xml file in a layout.
<?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">
<RelativeLayout
android:id="@+id/rl_content"
android:layout_width="match_parent"
android:layout_height="200dp">
<!-- 播放视频的VideoView -->
<com.teach.myapplication.MyVideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- 控制器 -->
<RelativeLayout
android:id="@+id/rl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<!-- 自定义样式后的SeekBar进度条 -->
<SeekBar
android:id="@+id/sb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/ll"
android:maxHeight="4dp"
android:minHeight="4dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:progressDrawable="@drawable/seekbar_shape"
android:thumb="@mipmap/icon_seekbar_button"
android:thumbOffset="20dp" />
<LinearLayout
android:paddingBottom="3dp"
android:id="@+id/ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="16dp"
android:orientation="horizontal">
<!-- 当前播放位置 -->
<TextView
android:id="@+id/tv_process_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textColor="#0E83F8"
android:textSize="13sp" />
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="/"
android:textColor="#FFFFFF"
android:textSize="13sp" />
<!-- 视频总时长 -->
<TextView
android:id="@+id/tv_all_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textColor="#FFFFFF"
android:textSize="13sp" />
</LinearLayout>
<!-- 全屏按钮 -->
<ImageView
android:paddingBottom="3dp"
android:id="@+id/iv_full_screen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="16dp"
android:src="@mipmap/icon_quanping" />
<!-- 播放暂停按钮 -->
<ImageView
android:id="@+id/iv_play_or_pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/sb"
android:layout_centerHorizontal="true"
android:src="@mipmap/icon_dianbo_play" />
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
3. Custom MediaView
/**
* 自定义的视频播放器
*/
public class MediaView extends FrameLayout implements SeekBar.OnSeekBarChangeListener, View.OnClickListener, MediaPlayer.OnPreparedListener, View.OnTouchListener {
/**
* 视频播放VideoView
*/
private MyVideoView videoView;
/**
* 进度SeekBar
*/
private SeekBar sb;
/**
* 播放总时长 和当前播放时长
*/
private TextView tv_process_date, tv_all_date;
/**
* 全屏播放按钮
*/
private ImageView iv_full_screen;
/**
* 播放或者暂停按钮
*/
private ImageView iv_play_or_pause;
/**
* 播放控制器
*/
private RelativeLayout rl, rl_content;
/**
* 是否正在播放视频
*/
private boolean playing;
/**
* 当前播放至的进度
*/
private int progress;
/**
* 时间定时器
*/
private Timer timer;
private TimerTask task;
private Handler handler;
/**
* 是否展示控制器
*/
private boolean showIng;
private Context context;
private boolean isFullScreen;
private int mHeight;
public MediaView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
this.context = context;
View view = LayoutInflater.from(context).inflate(R.layout.my_mediacontroller_layout, this, true);
videoView = view.findViewById(R.id.videoView);
sb = view.findViewById(R.id.sb);
sb.setOnSeekBarChangeListener(this);
tv_process_date = view.findViewById(R.id.tv_process_date);
tv_all_date = view.findViewById(R.id.tv_all_date);
iv_full_screen = view.findViewById(R.id.iv_full_screen);
iv_full_screen.setOnClickListener(this);
iv_play_or_pause = view.findViewById(R.id.iv_play_or_pause);
iv_play_or_pause.setOnClickListener(this);
rl = view.findViewById(R.id.rl);
rl_content = view.findViewById(R.id.rl_content);
videoView.setOnTouchListener(this);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
//do something
sb.setProgress(videoView.getCurrentPosition());
tv_process_date.setText(DateFormatUtils.getDateFormat(videoView.getCurrentPosition()));
} else if (msg.what == 2) {
rl.setVisibility(View.GONE);
showIng = false;
}
super.handleMessage(msg);
}
};
}
/**
* 播放器准备
*
* @param url
*/
public void start(String url) {
videoView.setVideoPath(url);
videoView.setOnPreparedListener(this);
}
/**
* 播放
*/
public void play() {
videoView.seekTo(videoView.getCurrentPosition());
playing = true;
videoView.start();
Log.e("lee", "播放的时候" + DateFormatUtils.getDateFormat(videoView.getCurrentPosition()));
Log.e("lee", "播放的时候" + videoView.getCurrentPosition());
timer = new Timer();
task = new TimerTask() {
@Override
public void run() {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
};
timer.schedule(task, 0, 1000);
handler.postDelayed(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = 2;
handler.sendMessage(message);
}
}, 5000);
iv_play_or_pause.setImageResource(R.mipmap.icon_dianbo_pause);
}
/**
* 暂停
*/
public void pause() {
videoView.pause();
Log.e("lee", "暂停的时候" + DateFormatUtils.getDateFormat(videoView.getCurrentPosition()));
Log.e("lee", "暂停的时候" + videoView.getCurrentPosition());
timer.cancel();
}
/**
* seekbar监听器
*/
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
tv_process_date.setText(DateFormatUtils.getDateFormat(progress));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
videoView.pause();
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
videoView.seekTo(seekBar.getProgress());
videoView.start();
playing = true;
iv_play_or_pause.setImageResource(R.mipmap.icon_dianbo_pause);
}
/**
* 点击事件
*
* @param v
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.iv_play_or_pause://播放暂停按钮
if (playing) {//正在播放 (点击暂停)
iv_play_or_pause.setImageResource(R.mipmap.icon_dianbo_play);
pause();
playing = false;
} else {//正在暂停 (点击播放)
iv_play_or_pause.setImageResource(R.mipmap.icon_dianbo_pause);
play();
playing = true;
}
break;
case R.id.iv_full_screen:
if (!isFullScreen) {//竖屏状态(切换成横屏)
//首先获得原来的高度
mHeight = rl_content.getHeight();
//重新制定高度
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) rl_content.getLayoutParams();
params.height = ViewGroup.LayoutParams.MATCH_PARENT;
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
((MainActivity) context).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);//显示顶部状态栏
((MainActivity) context).getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
((MainActivity) context).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
rl_content.setLayoutParams(params);
isFullScreen = true;
} else {//横屏状态(切换成竖屏)
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) rl_content.getLayoutParams();
params.height = mHeight;
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
((MainActivity) context).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏不 显示顶部状态栏
((MainActivity) context).getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
((MainActivity) context).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
rl_content.setLayoutParams(params);
isFullScreen = false;
}
break;
default:
break;
}
}
/**
* 视频加载成功
*
* @param mp
*/
@Override
public void onPrepared(MediaPlayer mp) {
sb.setMax(videoView.getDuration());
tv_process_date.setText(DateFormatUtils.getDateFormat(videoView.getCurrentPosition()));
tv_all_date.setText(DateFormatUtils.getDateFormat(videoView.getDuration()));
//播放
play();
/**
* 视频播放完成监听
*/
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
videoView.seekTo(0);
sb.setProgress(0);
playing = false;
rl.setVisibility(View.VISIBLE);
showIng = true;
iv_play_or_pause.setImageResource(R.mipmap.icon_dianbo_play);
}
});
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e("lee", "ACTION_DOWN");
rl.setVisibility(View.VISIBLE);
showIng = true;
if (showIng) {
handler.removeMessages(2);
}
break;
case MotionEvent.ACTION_MOVE:
Log.e("lee", "ACTION_MOVE");
if (showIng) {
handler.removeMessages(2);
}
break;
case MotionEvent.ACTION_UP:
Log.e("lee", "ACTION_DOWN");
handler.postDelayed(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = 2;
handler.sendMessage(message);
}
}, 5000);
break;
default:
break;
}
return true;
}
}
4. External call
Code in Activity
mediaView = findViewById(R.id.view);
mediaView.start("http://vfx.mtime.cn/Video/2019/06/26/mp4/190626111517361726.mp4");
xml code
<com.teach.myapplication.MediaView
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Note that Activity should be added in the manifest file
android:screenOrientation="portrait"
android:configChanges="orientation|screenSize|keyboardHidden"
5. The style of seekbar seekbar_shape.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="2dp" />
<solid android:color="#33FFFFFF" />
</shape>
</item>
<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="2dp" />
<solid android:color="#77FFFFFF" />
</shape>
</clip>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="2dp" />
<solid android:color="#0E83F8" />
</shape>
</clip>
</item>
</layer-list>
The above has completed the simple custom playback controller and can simply switch the playback function between horizontal and vertical screens, and the pause and playback icons will not be uploaded, just replace with your own name.