直接上圖
可進行三級縮放和拖動的視頻懸浮窗口
一、懸浮窗口
1.1、創建WindowManager
//創建params,控制大小位置
mParams = WindowManager.LayoutParams()
//懸浮窗口 mWindowManager = application.getSystemService(Context.WINDOW_SERVICE) as WindowManager
//權限要求 mParams.type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY } else { WindowManager.LayoutParams.TYPE_SYSTEM_ALERT }
1.2創建窗口界面
自定義一個View 包含視頻播放控件,關閉控件和縮放控件
1.3添加View
mParams.width = mSmallWidth mParams.height = mSmallHeight mParams.y = mHeight mWindowManager.addView(mVideoView, mParams)
這樣就創建一個懸浮窗口,通過控制Params width height控制大小,通過控制Param x、y控制位置
二、視頻播放
2.1 VideoVIew播放
直接使用VideoVIew控件進行視頻播放
mVideoView.setVideoURI(path)
mVideoView.start()
mVideoView.requestFocus()
mVideoView.setOnCompletionListener {
mVideoView.start()
}
主要本地文件的Uri不是很好獲取,目前通過FileProvider獲取,直接使用Uri.parse()獲取會出現無法找到文件的情況
val uri = FileProvider.getUriForFile(this, "com.js.floatingwindow.fileprovider", File(path))
2.2 SurfaceView播放
SurfaceView+MediaPlayer進行播放,比VideoView復雜一點,但是VideoVIew底層一樣的使用這種方式實現
播放使用MediaPlayer,SurfaceView進行圖像的展示,通過Player.setDisplay(holder)把兩者關聯起來,其他和音樂播放區別不大
mPlayer.isLooping = true try { mPlayer.setDatSource(path.toString()) } catch (e: Exception) { } mPlayer.prepareAsync() mPlayer.setOnPreparedListener { mPlayer.start() }
2.3 縮放
放大縮小時,視頻需要跟着變化,這個改變方式兩者不一樣
VideoView比較簡單
viewTreeObserver.addOnGlobalLayoutListener {
mVideoView.run {
holder.setFixedSize(width,height)
requestLayout()
}
}
SurfaceView
fun changeVideoSize() { try { var width: Int = mPlayer.videoWidth var height: Int = mPlayer.videoHeight val surfaceWidth = getWidth() val surfaceHeight = getHeight() val max: Float = Math.max(width / surfaceWidth.toFloat(), height / surfaceHeight.toFloat()) width = Math.ceil((width / max).toDouble()).toInt() height = Math.ceil((height / max).toDouble()).toInt() val params = FrameLayout.LayoutParams(width, height) params.gravity = Gravity.CENTER mVideoView.layoutParams = params mVideoView.invalidate() } catch (e: IllegalStateException) { //mPlayer可能出現異常 } }
有用的話幫忙加個星哦,歡迎討論