项目需求
在视频播放器页面,当我们对视频进行操作时,会出现很多控件,当无操作之后,需要在无操作三秒后隐藏这些控件。
项目解决方案
使用View视图自带的Handler方法,不需要自己创建Timer定时器。
项目代码
1.创建一个视图
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.ScreenActivity">
<SurfaceView
android:id="@+id/sv_video"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/ll_screen_top"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="#1A534D4D">
<ImageView
android:id="@+id/iv_screen_close"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:scaleType="centerInside"
android:src="@drawable/ic_return_white" />
<TextView
android:id="@+id/tv_screen_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="10dp"
android:gravity="center_vertical"
android:text="这是视频的名称"
android:textColor="#FFFFFF"
android:textSize="15sp" />
</LinearLayout>
<ImageView
android:id="@+id/iv_screen_play"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_centerInParent="true"
android:background="@drawable/ic_video_start" />
</RelativeLayout>
这是原始截图,比较简单
2.Activity里面代码
class ScreenActivity : AppCompatActivity() {
private lateinit var binding: ActivityScreenBinding
private val HIDE_VIEW_TIME = 3000L //无操作后在多长时间后隐藏视图
private var isPlaying = false //视频是否在播放
private var isShowView = false //界面控件是否显示
private var mediaPlayer: MediaPlayer? = null//视频播放
...... //部分代码省略
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityScreenBinding.inflate(layoutInflater)
setContentView(binding.root)
...... //部分代码省略
//退出按钮
binding.ivScreenClose.setOnClickListener { finish() }
//点击中间的播放按钮的操作
binding.ivScreenPlay.setOnClickListener {
if (mediaPlayer?.isPlaying == true) {
pausePlayer()
} else {
startPlayer()
}
}
}
//播放视频
private fun startPlayer() {
mediaPlayer?.play()
isPlaying = true
binding.ivScreenPlay.setImageResource(R.drawable.ic_video_pause)
postView()
}
//暂停视频
private fun pausePlayer() {
mediaPlayer?.pause()
isPlaying = false
binding.ivScreenPlay.setImageResource(R.drawable.ic_video_start)
postView()
}
//释放视频
private fun releasePlayer() {
if (mediaPlayer == null) return
mediaPlayer?.stop()
mediaPlayer = null
isPlaying = false
}
//Activity销毁
override fun onDestroy() {
super.onDestroy()
releasePlayer()
binding.svVideo.removeCallbacks(runHideView)
}
private fun postView() {
//将runHideView从Handler消息队列里面去除(当对界面有操作的时候,
//需要清除掉原来的任务,然后传一个新的任务,
//这样才能一直保持是3秒无操作隐藏的效果)
binding.svVideo.removeCallbacks(runHideView)
//经过HIDE_VIEW_TIME时间后往Handler队列里面post一个runHideView
binding.svVideo.postDelayed(runHideView, HIDE_VIEW_TIME)
}
//runHideView继承Runnable接口
private val runHideView: Runnable = Runnable {
hideView()
}
//显示页面控件
private fun showView() {
isShowView = true
binding.llScreenTop.visibility = View.VISIBLE
if (isPlaying) {
binding.ivScreenPlay.setImageResource(R.drawable.ic_video_pause)
} else {
binding.ivScreenPlay.setImageResource(R.drawable.ic_video_start)
}
binding.ivScreenPlay.visibility = View.VISIBLE
binding.svVideo.removeCallbacks(runHideView)
binding.svVideo.postDelayed(runHideView, HIDE_VIEW_TIME)
}
//隐藏页面控件
private fun hideView() {
isShowView = false
binding.llScreenTop.visibility = View.GONE
binding.ivScreenPlay.visibility = View.GONE
}
//屏幕点击事件监听
override fun onTouchEvent(event: MotionEvent?): Boolean {
if (event?.action == MotionEvent.ACTION_DOWN) {
if (!isShowView) {
showView()
}
}
return super.onTouchEvent(event)
}
}
实现需求功能主要还是使用了View里面带的postDelayed方法实现了定时功能,实际上就是Handler的postDelayed方法
View关于此方法的源码
/**
* <p>Causes the Runnable to be added to the message queue, to be run
* after the specified amount of time elapses.
* The runnable will be run on the user interface thread.</p>
*
* @param action The Runnable that will be executed.
* @param delayMillis The delay (in milliseconds) until the Runnable
* will be executed.
*
* @return true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the Runnable will be processed --
* if the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*
* @see #post
* @see #removeCallbacks
*/
public boolean postDelayed(Runnable action, long delayMillis) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.postDelayed(action, delayMillis);
}
// Postpone the runnable until we know on which thread it needs to run.
// Assume that the runnable will be successfully placed after attach.
getRunQueue().postDelayed(action, delayMillis);
return true;
}
PS:一位大神的视频播放器地址链接: 参考链接