package com.ydl.media.view import android.annotation.SuppressLint import android.content.Context import android.graphics.PixelFormat import android.graphics.Point import android.os.Build import android.text.TextUtils import android.view.* import android.widget.FrameLayout import com.bumptech.glide.Glide import com.ydl.media.R import com.ydl.media.audio.AudioPlayer import com.ydl.media.audio.OnPlayerEventListener import com.ydl.media.audio.model.Music import com.ydl.ydl_image.transform.GlideRoundTransform import com.ydl.ydlcommon.utils.statusBar.StatusBarUtil import com.yidianling.common.tools.RxImageTool import kotlinx.android.synthetic.main.item_playing_float_btn.view.* import kotlin.math.abs class PlayerFloatView(ctx: Context) : FrameLayout(ctx.applicationContext) { private var mTouchDownX: Float = 0.toFloat() private var mTouchDownY: Float = 0.toFloat() private var mTouchX: Float = 0.toFloat() private var mTouchY: Float = 0.toFloat() private val mTouchSlop: Int = (ViewConfiguration.get(context).scaledTouchSlop + 8) * 3 private val mWindowManager: WindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager //全局变量,用以保存悬浮窗口的属性 var mFloatViewParams = WindowManager.LayoutParams() private var mFloatViewPlayListeners = HashSet<FloatViewPlayListener>() private var mAudioPlayListener: OnPlayerEventListener? = null private val mStatusBarHeight: Int = StatusBarUtil.getStatusBarHeight(context) init { View.inflate(context, R.layout.item_playing_float_btn, this) resetFloatView() if (!TextUtils.isEmpty(AudioPlayer.get().playMusic?.coverPath)) { Glide.with(context) .load(AudioPlayer.get().playMusic?.coverPath) .transform(GlideRoundTransform(context, 4)) .error(R.drawable.ico_play_float_pic) .into(play_head) } cl.setOnClickListener { if (PlayerFloatHelper.isCanClick) { PlayerFloatHelper.startPlayingActivity(context) } } play_close.setOnClickListener { mFloatViewPlayListeners.forEach { if (!it.onPreClose()) return@setOnClickListener } mFloatViewPlayListeners.forEach { it.onPauseClick() } PlayerFloatHelper.removeResetView() } play_state.setOnClickListener { if (AudioPlayer.get().isPlaying) { AudioPlayer.get().pausePlayer() mFloatViewPlayListeners.forEach { it.onPauseClick() } } else if (AudioPlayer.get().isPausing) { AudioPlayer.get().startPlayer() mFloatViewPlayListeners.forEach { it.onStartClick() } } } if (mAudioPlayListener == null) { mAudioPlayListener = object : OnPlayerEventListener { override fun onComplete() { tv_start.text = getStringTime(AudioPlayer.get().getDuration().toInt()) setPlayDrawable() mFloatViewPlayListeners.forEach { it.onPlayFinish() } } override fun onPreLoad(playPosition: Int): Boolean { AudioPlayer.get().getMusicList().elementAtOrNull(playPosition)?.let { return if (it.canPlay) { tv_title.text = it.title tv_name.text = it.artist true } else { AudioPlayer.get().load(AudioPlayer.get().getNextPosition(playPosition)) false } } return true } override fun onLoad(music: Music) { } override fun onStartPlay() { setPauseDrawable() } override fun onPausePlay() { setPlayDrawable() } @SuppressLint("SetTextI18n") override fun onPublish(percent: Int, currentPosition: Long) { tv_start.text = getStringTime(currentPosition.toInt()) } override fun onBufferingUpdate(percent: Int) { } @SuppressLint("SetTextI18n") override fun onPrepared(duration: Long) { setDuration() updatePlayState() } } AudioPlayer.get().addOnPlayEventListener(mAudioPlayListener!!) } } @SuppressLint("SetTextI18n") private fun resetFloatView() { if (!TextUtils.isEmpty(AudioPlayer.get().playMusic?.coverPath)) { Glide.with(context) .load(AudioPlayer.get().playMusic?.coverPath) .transform(GlideRoundTransform(context, 4)) .error(R.drawable.ico_play_float_pic) .into(play_head) } if (TextUtils.isEmpty(AudioPlayer.get().playMusic?.title)) { if (PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_FM) { tv_title.text = "心灵电台" } if (PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_CONFIDE) { tv_title.text = "壹点倾诉,心灵寄语" } } else { tv_title.text = AudioPlayer.get().playMusic?.title } tv_name.text = if (TextUtils.isEmpty(AudioPlayer.get().playMusic?.artist)) { "壹点灵" } else { AudioPlayer.get().playMusic?.artist } setDuration() } @SuppressLint("SetTextI18n") private fun setDuration() { tv_duration.text = " / ${getStringTime(AudioPlayer.get().getDuration().toInt())}" } private fun getStringTime(time: Int): String { if (time <= 0) return "00:00" val min = time / 60000 val ss = (time - min * 60000) / 1000 var m = "" + min var s = "" + ss if (min < 10) { m = "0$m" } if (ss < 10) { s = "0$ss" } return "$m:$s" } override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { when (ev.action) { MotionEvent.ACTION_DOWN -> { mTouchDownY = ev.y } MotionEvent.ACTION_MOVE -> { val moveY = ev.y if (abs(moveY - mTouchDownY) > mTouchSlop) { return true } } MotionEvent.ACTION_UP -> { mTouchDownY = 0f } } return super.onInterceptTouchEvent(ev) } override fun onTouchEvent(event: MotionEvent): Boolean { //获取相对屏幕的坐标,即以屏幕左上角为原点 mTouchX = event.rawX mTouchY = event.rawY when (event.action) { MotionEvent.ACTION_DOWN -> { //获取相对View的坐标,即以此View左上角为原点 mTouchDownX = event.x mTouchDownY = event.y } MotionEvent.ACTION_MOVE -> updateFloatViewPosition() MotionEvent.ACTION_UP -> { updateFloatViewPosition() mTouchDownY = 0f mTouchDownX = mTouchDownY } } return super.onTouchEvent(event) } private fun updateFloatViewPosition() { //更新浮动窗口位置参数 mFloatViewParams.x = (mTouchX - mTouchDownX).toInt() mFloatViewParams.y = (mTouchY - mTouchDownY - mStatusBarHeight).toInt() mWindowManager.updateViewLayout(this, mFloatViewParams) } fun updatePlayState() { if (AudioPlayer.get().isPlaying) { setPauseDrawable() } else { setPlayDrawable() for (listener in mFloatViewPlayListeners) { listener.onPauseClick() } } } private fun setPlayDrawable() { play_state.setImageResource(R.drawable.ico_yyfc_play) } private fun setPauseDrawable() { play_state.setImageResource(R.drawable.ico_yyfc_pause) } fun setPlayingState() { setPauseDrawable() resetFloatView() } fun show(): PlayerFloatView { mWindowManager.addView(this, mFloatViewParams.apply { type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; } else { WindowManager.LayoutParams.TYPE_PHONE; } format = PixelFormat.RGBA_8888 // 设置图片格式,效果为背景透明 flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE gravity = Gravity.START or Gravity.TOP // 调整悬浮窗口至左上角 val size = Point() // 以屏幕左上角为原点,设置x、y初始值 mWindowManager.defaultDisplay?.getSize(size) x = 0 y = size.y * 5 / 6 //设置悬浮窗口长宽数据 width = WindowManager.LayoutParams.MATCH_PARENT height = RxImageTool.dp2px(56f) }) return this } fun remove() { mFloatViewPlayListeners.clear() mAudioPlayListener?.let { AudioPlayer.get().removeOnPlayEventListener(it) } mWindowManager.removeViewImmediate(this) } fun removeAndReset() { AudioPlayer.get().resetPlayer() remove() } fun addFloatClickListener(floatClickListener: FloatViewPlayListener) { mFloatViewPlayListeners.add(floatClickListener) } fun removeFloatClickListener(floatClickListener: FloatViewPlayListener) { mFloatViewPlayListeners.remove(floatClickListener) } interface FloatViewPlayListener { fun onPauseClick() {} fun onStartClick() {} fun onPlayFinish() {} /** * @return true: 允许关闭 */ fun onPreClose(): Boolean = true } }