美文网首页
Android VideoView简易MediaControll

Android VideoView简易MediaControll

作者: 简夕_bcb0 | 来源:发表于2020-08-12 20:19 被阅读0次

        最近在手表上(安卓系统)做相机、相册、聊天应用,想着业务逻辑简单,不需要使用功能强大的第三方视频库,Android自带的VideoView正好合适,略遗憾的是搭配VideoView使用的MediaController无法定制,网上有不少文章说拷贝源码重写一个,但是我卡住其中一步:无法通过反射获取到PhoneWindow,惨败收场。。。

播放控制器

        我的需求其实是非常简单的:1、轻触屏幕唤起控制器;2、1秒后自动隐藏;3、支持播放、暂停、向前10秒、向后10秒、拖动播放

代码如下:

class JXMediaController : ConstraintLayout {

/**

* 控制哪个VideoView,必须

*/

    var videoView: VideoView? =null

        set(value) {

field = value

initVideoListener()

}

/**

* 显示时长

*/

    var hideMilliseconds =1_000

    private var mShowing =false

    private var mDragging =false

    private val mFormatBuilder = StringBuilder()

private val mFormatter = Formatter(mFormatBuilder, Locale.getDefault())

constructor(context: Context) :this(context,null){}

    constructor(context: Context, attrs: AttributeSet?) :super(context, attrs) {

View.inflate(context, R.layout.media_controller,this)

pause_btn.setOnClickListener{

            pauseOrPlay()

}

        backward_btn.setOnClickListener{

            backward()

}

        forward_btn.setOnClickListener{

            forward()

}

        seek_bar.setOnSeekBarChangeListener(mSeekListener)

}

//前进10秒

    private fun forward() {

val videoView =videoView ?:return

        if (!videoView.canSeekForward())return

        val remain = videoView.duration - videoView.currentPosition

        if (remain >10_000) {

videoView.seekTo(videoView.currentPosition +10_000)

show()

}

//        updateProgress(videoView.currentPosition, videoView.duration)

    }

//回退10秒

    private fun backward() {

val videoView =videoView ?:return

        if (!videoView.canSeekBackward())return

        if (videoView.currentPosition >10_000) {

videoView.seekTo(videoView.currentPosition -10_000)

show()

}

//        updateProgress(videoView.currentPosition, videoView.duration)

    }

private fun pauseOrPlay() {

val videoView =videoView ?:return

        if (videoView.isPlaying) {

videoView.pause()

pause_btn.setImageResource(R.mipmap.media_play)

}else {

videoView.start()

pause_btn.setImageResource(R.mipmap.media_pause)

}

show()

}

private fun initVideoListener() {

val videoView =videoView ?:return

        videoView.setOnPreparedListener{

            if (mShowing) {

updatePausePlay()

}

}

        videoView.setOnCompletionListener{

            if (mShowing) {

updatePausePlay()

}

}

        videoView.setOnErrorListener{ mp, what, extra->

            if (mShowing) {

updatePausePlay()

}

true

        }

        videoView.setOnInfoListener{ mp, what, extra->

            LogI("on info ....")

if (mShowing) {

updateProgress(mp.currentPosition, mp.duration)

}

true

        }

        videoView.setOnClickListener{

            if (!mShowing) {

show()

}

}

    }

//更新暂停/开始按钮

    private fun updatePausePlay() {

val videoView =videoView ?:return

        if (videoView.isPlaying) {

pause_btn.setImageResource(R.mipmap.media_pause)

}else {

pause_btn.setImageResource(R.mipmap.media_play)

}

}

private fun updateProgress() {

val videoView =videoView ?:return

        updateProgress(videoView.currentPosition, videoView.duration)

}

//更新进度

    private fun updateProgress(position: Int, duration: Int) {

if (duration >0) {

val pos: Long =1000L * position / duration

seek_bar.progress = pos.toInt()

}

time_current_tv.text = stringForTime(position)

time_tv.text = stringForTime(duration)

}

//显示

    fun show() {

show(hideMilliseconds)

}

fun show(timeout: Int) {

if (!mShowing) {

pause_btn.requestFocus()

visibility = View.VISIBLE

            mShowing =true

        }

updatePausePlay()

post(mShowProgress)

if (timeout !=0) {

removeCallbacks(mFadeOut)

postDelayed(mFadeOut, timeout.toLong())

}

}

fun hide() {

if (mShowing) {

removeCallbacks(mShowProgress)

visibility = View.GONE

            mShowing =false

        }

}

private fun stringForTime(timeMs: Int): String? {

val totalSeconds = timeMs /1000

        val seconds = totalSeconds %60

        val minutes = totalSeconds /60 %60

        val hours = totalSeconds /3600

        mFormatBuilder.setLength(0)

return if (hours >0) {

mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString()

}else {

mFormatter.format("%02d:%02d", minutes, seconds).toString()

}

}

private val mFadeOut =Runnable { hide()}

    private val mShowProgress: Runnable =object : Runnable {

override fun run() {

updateProgress()

if (!mDragging &&mShowing &&videoView!!.isPlaying()) {

postDelayed(this,1000 - (videoView!!.currentPosition %1000).toLong())

}

}

}

private val mSeekListener: OnSeekBarChangeListener =object : OnSeekBarChangeListener {

override fun onStartTrackingTouch(bar: SeekBar) {

mDragging =true

            removeCallbacks(mFadeOut)

removeCallbacks(mShowProgress)

}

override fun onProgressChanged(bar: SeekBar, progress: Int, fromuser: Boolean) {

if (!fromuser)return

            val videoView =videoView ?:return

            val duration: Long = videoView.duration.toLong()

val newPosition = duration * progress /1000L

            videoView.seekTo(newPosition.toInt())

time_current_tv.text = stringForTime(newPosition.toInt())

}

override fun onStopTrackingTouch(bar: SeekBar) {

mDragging =false

//            updatePausePlay()

            show()

//            post(mShowProgress)

        }

}

}

布局很简单,相信你也能猜出来。感谢阅读

相关文章

网友评论

      本文标题:Android VideoView简易MediaControll

      本文链接:https://www.haomeiwen.com/subject/fwwmdktx.html