一、使用系统自带的VideoView播放视频
- 在资源文件中添加VideoView标签
<VideoView
android:id="@+id/sys_video"
android:layout_width="match_parent"
android:layout_height="280dp"/>
- 在Activity类中调用
val path = Environment.getExternalStorageDirectory().absolutePath+"/hello.mp4"
val controller = MediaController(this)
sys_video.setMediaController(controller)
sys_video.setVideoPath(path)
sys_video.setVideoURI(Uri.parse(path))
sys_video.start()
注意: 当视频无法播放时,一般可能为无法打开此视频文件,此时需注意软件是否含有读取文件的权限。在读取文件之前要确保软件已经获取了文件的访问权限。
二、自定义播放器
1. 新建播放器样式文件
根据页面设计要求编写video显示页面的样式文件。
<?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"
app:layoutDescription="@xml/activity_main_scene"
tools:context=".MainActivity">
<RelativeLayout
android:id="@+id/layout_view"
android:layout_width="match_parent"
android:layout_height="300dp">
<VideoView
android:id="@+id/sys_video"
android:layout_width="match_parent"
android:layout_height="250dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:orientation="vertical">
<SeekBar
android:id="@+id/progress_bar"
android:layout_width="match_parent"
android:layout_height="5dp"
android:thumb="@null" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#101010"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp" />
<TextView
android:id="@+id/time_remain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="00:00:00"
android:textColor="#ffffff"
android:textSize="25dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="/"
android:textColor="#4c4c4c"
android:textSize="25dp" />
<TextView
android:id="@+id/time_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="00:00:00"
android:textColor="#4c4c4c"
android:textSize="25dp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:layout_alignParentRight="true"
android:orientation="horizontal">
<View
android:layout_width="1dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" />
<ImageView
android:id="@+id/voice_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/voice_icon"
android:visibility="gone" />
<SeekBar
android:id="@+id/voice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:thumb="@null"
android:visibility="gone" />
<ImageButton
android:id="@+id/full_screen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/full_screen_icon"
/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
2. 添加响应函数
fun videoOrButtonClick(){
if(sys_video.isPlaying){
start_pause.setImageResource(R.drawable.pause_image)
sys_video.pause()
myHandler.removeMessage(MSG_UPDATE)
}else{
start_pause.setImageResource(R.drawable.start_image)
sys_video.start()
myHandler.sendEmptyMessage(MSG_UPDATE)
}
}
fun setClickEvent(){
start_pause.setOnclickListener(){
videoOrButtonClick()
}
sys_video.setOnclickListener(){
videoOrButtonClick()
}
progress_bar.setOnSeekBarChangeListener(object:OnSeekBarChangeListener{
override fun onProgressChanged(seekBar:SeekBar?, progress:Int, fromUser:Boolean){
time_remain.text = positionToTime(progress)
}
override fun onStartTrackingTouch(seekBar:SeekBar?){
myHandler.removeMessage(MSG_UPDATE)
}
override fun onStopTrackingTouch(seekBar:SeekBar?){
sys_video.seekTo(seekBar!!.progress)
myHandler.sendEmptyMessage(MSG_UPDATE)
}
})
}
3.实现页面数据填充
3.1 实现页面数据定时刷新
val MSG_UPDATE = 1
inner class MyHandler:Handler(){
override fun handleMessage(message:Message){
if(message.what == MSG_UPDATE){
time_total.text = positionToTimeString(sys_video.duration)
time_remain.text = positionToTime(sys_video.currentPosition)
progress_bar.max = sys_video.duration
progress_bar.progress = sys_video.currentPosition
sendEmptyMessageDelayed(MSG_UPDATE, 500)
}
}
}
4.实现横竖屏切换
4.1 横竖屏切换时视频会从新开始播放,此时需要在AndroidManifest.xml中添加confgChanges
<activity
android:configChanges="screenSize|keyboard|orientation|keyboardHidden
android:name=".MainActivity"
>"
4.2 设置横竖屏屏幕大小
说明:此时视频可切换成横屏状态,但是视频大小无法拉伸,若需要视频可自适应屏幕大小,则需自定义VideoView
fun setVideoViewScale(width:Int, height:Int){
sys_video.layoutParams.width = width
sys_video.layoutParams.heigth = height
layout_view.layoutParams.width = width
layout_view.layoutParams.heigth = height
}
val Int.dp: Int
get() = android.util.TypedValue.applyDimension(
android.util.TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics).toInt()
override fun onConfigurationChanged(newConfig:Configuration){
super.onConfigurationChanged(newConfig)
if(resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE){
setVideoViewScale(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)
}
else{
setVideoViewScale(ViewGroup.LayoutParams.MATCH_PARENT, 250.dp)
}
}
5. 添加音量设置
5.1 获得audioService
private lateinit var audioService:AudioManager
在Activity的OnCreate中获得服务。并设置最大音量和当前音量
切记:在OnCreate 之前是无法获得服务的
audioService = getSystemService(AUDIO_SERVICE) as AudioManager
voice.max = audioService.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
voice.progress = audioService.getStreamVolume(AudioManager.STREAM_MUSIC)
5.2 添加voice seekBar的监听函数
voice.setOnSeekBarChangeListener(object:OnSeekBarChangeListener{
override fun onProgressChanged(seekBar:SeekBar?, progress:Int, fromUser:Boolean){
audioService.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0)
}
override fun onStartTrackingTouch(seekBar:SeekBar?){
}
override fun onStopTrackingTouch(seekBar:SeekBar?){}
})
5.3 设置横屏时voice 进度条可见
在sys_video的监听函数中添加:横屏时设置voice 进度条可见,竖屏时隐藏。
voice.visibility = VISIBLE
voice_icon.visibility = VISIBLE
voice.visibility = GONE
voice_icon.visibility = GONE
6. 按键切换全屏和半屏
private var fullScreen = false
full_screen.setOnClickListener{
if(fullScreen){
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
else{
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
}
}
7. 设置适应全屏
7.1 自定义VideoView继承自VideoView
class MyVideoView(context:Context, attrs:AttributeSet?):VideoView(context,attrs){
val default_Width = 1920
val default_Height = 1080
override fun onMeasure(widthMeasureSpec:Int,heightMeasureSpec:Int){
super.onMesure(widthMeasureSpec, heightMeasureSpec)
var width = getDefaultSize(default_Width, widthMeasureSpec)
var height = getDefaultSize(default_Height, heightMeasureSpec)
setMeasureDimension(width, height)
}
}
7.2 更改xml文件中的组件类型
将样式文件中的 <VideoView 标签改为:<com.example.myvideo.MyVideoView
7.3 更新横竖屏监听函数
window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
8. 滑动屏幕调节音量和亮度
获取滑动事件
sys_video.setOnTouchListener(v,event->
var X = event!!.getX()
var Y = event!!.getY()
when(event!!.action){
MotionEvent.ACTION_DOWN->{
}
MotionEvent.ACTION_MOVE->{}
MotionEvent.ACTION_UP->{}
}
true
)
根据初始位置判断更改亮度还是声音。
调节屏幕亮度:
window.attributes.screenBrightness += detlaBright
|