package com.ydl.media.view import android.annotation.SuppressLint import android.content.Context import android.os.Handler import android.os.Message import android.text.TextUtils import android.util.Log import android.view.MotionEvent import android.view.View import android.view.ViewConfiguration import android.view.WindowManager import android.widget.* 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.module.GlideApp import com.ydl.ydl_image.transform.GlideRoundTransform import java.util.* import java.util.concurrent.CopyOnWriteArraySet class PlayerFloatView(var mContext: Context) : FrameLayout(mContext) { private var mTouchStartX: Float = 0.toFloat() private var mTouchStartY: Float = 0.toFloat() private var mCurrX: Float = 0.toFloat() private var mCurrY: Float = 0.toFloat() private var playState: ImageView? = null private var mAudioLayout: LinearLayout? = null private var mInfoLayout: RelativeLayout? = null private var playClose: ImageView? = null private var playHead: ImageView? = null private var titleView: TextView? = null private var nameView: TextView? = null private var currentPlayingTimeView: TextView? = null private var durationView: TextView? = null private var mTouchSlop: Int = 0 private var time: Int = 0 private var allTime: Int = 0 private var isMove: Boolean = false private var wm: WindowManager? = null //此wmParams为获取的全局变量,用以保存悬浮窗口的属性 var wmParams = WindowManager.LayoutParams() private var myHandler: Handler? = null private val UPDATE_VIEW_STATE = 1 private val UPDATE_VIEW_COMPLETE = 2 private val UPDATE_PLAY_TIME = 3//更新播放时间 private var listeners: CopyOnWriteArraySet<FloatViewPlayListener> = CopyOnWriteArraySet() private var mStateChangeListener: OnPlayerEventListener? = null private var playData: HashMap<String, String> = hashMapOf<String, String>() init { init(context) } fun resetWm(context: Context) { wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager wmParams = WindowManager.LayoutParams() } fun resetView() { resetAudioView() } @SuppressLint("ClickableViewAccessibility") private fun init(context: Context) { wm = getContext().getSystemService(Context.WINDOW_SERVICE) as WindowManager mTouchSlop = (ViewConfiguration.get(getContext()).scaledTouchSlop + 8) * 3 val view = View.inflate(context, R.layout.item_playing_float_btn, this) mAudioLayout = view.findViewById(R.id.ll_audio_layout) mInfoLayout = view.findViewById(R.id.rl_info) playHead = view.findViewById(R.id.play_head) playState = view.findViewById(R.id.play_state) playClose = view.findViewById(R.id.play_close) titleView = view.findViewById(R.id.tv_title) nameView = view.findViewById(R.id.tv_name) currentPlayingTimeView = view.findViewById(R.id.tv_now_playing_time) durationView = view.findViewById(R.id.tv_duration) resetAudioView() if (!TextUtils.isEmpty(AudioPlayer.get().playMusic?.coverPath)) { GlideApp.with(context.applicationContext) .load(AudioPlayer.get().playMusic?.coverPath) .transform(GlideRoundTransform(context, 4)) .error(R.drawable.ico_play_float_pic) .into(playHead!!) } myHandler = MyHandler() playHead!!.setOnTouchListener { _, event -> mCurrX = event.rawX mCurrY = event.rawY - 25 when (event.action) { MotionEvent.ACTION_DOWN -> { //获取相对View的坐标,即以此View左上角为原点 mTouchStartX = event.x mTouchStartY = event.y } MotionEvent.ACTION_MOVE -> { if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop) { updateViewPosition() isMove = true } } MotionEvent.ACTION_UP -> { if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop || isMove ) { updateViewPosition() } else { if (!isMove) { if (PlayerFloatHelper.isCanClick) { PlayerFloatHelper.startPlayingActivity(context) } } } isMove = false mTouchStartY = 0f mTouchStartX = mTouchStartY } } true } titleView!!.setOnTouchListener { _, event -> mCurrX = event.rawX mCurrY = event.rawY - 25 when (event.action) { MotionEvent.ACTION_DOWN -> { //获取相对View的坐标,即以此View左上角为原点 mTouchStartX = event.x mTouchStartY = event.y } MotionEvent.ACTION_MOVE -> { if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop) { updateViewPosition() isMove = true } } MotionEvent.ACTION_UP -> { if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop || isMove ) { updateViewPosition() } else { if (!isMove) { if (PlayerFloatHelper.isCanClick) { PlayerFloatHelper.startPlayingActivity(context) } } } isMove = false mTouchStartY = 0f mTouchStartX = mTouchStartY } } true } nameView!!.setOnTouchListener { _, event -> mCurrX = event.rawX mCurrY = event.rawY - 25 when (event.action) { MotionEvent.ACTION_DOWN -> { //获取相对View的坐标,即以此View左上角为原点 mTouchStartX = event.x mTouchStartY = event.y } MotionEvent.ACTION_MOVE -> { if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop) { updateViewPosition() isMove = true } } MotionEvent.ACTION_UP -> { if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop || isMove ) { updateViewPosition() } else { if (!isMove) { if (PlayerFloatHelper.isCanClick) { PlayerFloatHelper.startPlayingActivity(context) } } } isMove = false mTouchStartY = 0f mTouchStartX = mTouchStartY } } true } playClose!!.setOnTouchListener { _, event -> mCurrX = event.rawX mCurrY = event.rawY - 25 when (event.action) { MotionEvent.ACTION_DOWN -> { //获取相对View的坐标,即以此View左上角为原点 mTouchStartX = event.x mTouchStartY = event.y } MotionEvent.ACTION_MOVE -> { if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop) { updateViewPosition() isMove = true } } MotionEvent.ACTION_UP -> { if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop || isMove ) { updateViewPosition() } else { if (!isMove) { for (listener in listeners) { //数据重新设置回调 listener.onPauseClick() } this@PlayerFloatView.visibility = View.GONE PlayerFloatHelper.removeView(mContext) PlayerFloatHelper.playTempData.clear() AudioPlayer.get().stopPlayer() } } isMove = false mTouchStartY = 0f mTouchStartX = mTouchStartY } } true } playState!!.setOnTouchListener { _, event -> mCurrX = event.rawX mCurrY = event.rawY - 25 when (event.action) { MotionEvent.ACTION_DOWN -> { //获取相对View的坐标,即以此View左上角为原点 mTouchStartX = event.x mTouchStartY = event.y } MotionEvent.ACTION_MOVE -> { if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop) { updateViewPosition() isMove = true } } MotionEvent.ACTION_UP -> { if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop || isMove ) { updateViewPosition() } else { if (!isMove) { if (AudioPlayer.get().isPlaying) { playState!!.setImageResource(R.drawable.ico_yyfc_play) AudioPlayer.get().playPause() for (listener in listeners) { //数据重新设置回调 listener.onPauseClick() } } else { playState!!.setImageResource(R.drawable.ico_yyfc_pause) AudioPlayer.get().playPause() for (listener in listeners) { //数据重新设置回调 listener.onStartClick() } } } } isMove = false mTouchStartY = 0f mTouchStartX = mTouchStartY } } true } if (mStateChangeListener == null) { mStateChangeListener = object : OnPlayerEventListener { override fun onComplete() { myHandler?.sendEmptyMessage(UPDATE_VIEW_COMPLETE) } override fun onChange(music: Music) { } override fun onPlayerStart() { } override fun onPlayerPause() { } override fun onPublish(percent: Int, currentPosition: Long) { this@PlayerFloatView.time = currentPosition.toInt() myHandler?.sendEmptyMessage(UPDATE_PLAY_TIME) } override fun onBufferingUpdate(percent: Int) { } override fun onPrepared(duration: Long) { this@PlayerFloatView.allTime = duration.toInt() myHandler?.sendEmptyMessage(UPDATE_PLAY_TIME) myHandler?.sendEmptyMessage(UPDATE_VIEW_STATE) } } AudioPlayer.get().addOnPlayEventListener(mStateChangeListener!!) } } private fun resetAudioView() { if (!TextUtils.isEmpty(AudioPlayer.get().playMusic?.coverPath)) { GlideApp.with(context.applicationContext) .load(AudioPlayer.get().playMusic?.coverPath) .transform(GlideRoundTransform(context, 4)) .error(R.drawable.ico_play_float_pic) .into(playHead!!) } if (TextUtils.isEmpty(AudioPlayer.get().playMusic?.title)) { if (PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_FM) { titleView!!.text = "心灵电台" } if (PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_CONFIDE) { titleView!!.text = "壹点倾诉,心灵寄语" } } else { titleView!!.text = AudioPlayer.get().playMusic?.title } if (TextUtils.isEmpty(AudioPlayer.get().playMusic?.artist)) { nameView!!.text = "壹点灵" } else { nameView!!.text = AudioPlayer.get().playMusic?.artist } mAudioLayout!!.visibility = View.VISIBLE } private fun getStringTime(time: Int): String { if (time <= 0) return "00:00" var min = time / 60000 var ss = (time - min * 60000) / 1000 var mm = "" + min var SS = "" + ss if (min < 10) { mm = "0$mm" } if (ss < 10) { SS = "0$ss" } return "$mm:$SS" } private fun updatePlayTime() { currentPlayingTimeView?.text = getStringTime(time) durationView?.text = getStringTime(allTime) } override fun onTouchEvent(event: MotionEvent): Boolean { //获取相对屏幕的坐标,即以屏幕左上角为原点 mCurrX = event.rawX mCurrY = event.rawY - 25 Log.i("currP", "currX$mCurrX====currY$mCurrY") when (event.action) { MotionEvent.ACTION_DOWN -> { //获取相对View的坐标,即以此View左上角为原点 mTouchStartX = event.x mTouchStartY = event.y } MotionEvent.ACTION_MOVE -> updateViewPosition() MotionEvent.ACTION_UP -> { updateViewPosition() mTouchStartY = 0f mTouchStartX = mTouchStartY } } return true } private fun updateViewPosition() { //更新浮动窗口位置参数 wmParams.x = (mCurrX - mTouchStartX).toInt() wmParams.y = (mCurrY - mTouchStartY).toInt() wm!!.updateViewLayout(this, wmParams) } fun updatePlayState() { if (AudioPlayer.get().isPlaying) { playState!!.setImageResource(R.drawable.ico_yyfc_pause) } else { playState!!.setImageResource(R.drawable.ico_yyfc_play) for (listener in listeners) { listener.onPauseClick() } } } fun setPlayingState() { playState!!.setImageResource(R.drawable.ico_yyfc_pause) resetAudioView() } fun onDestroy() { listeners.clear() mStateChangeListener?.let { AudioPlayer.get().removeOnPlayEventListener(it) } } fun addFloatClickListener(floatClickListener: FloatViewPlayListener) { listeners.add(floatClickListener) } fun removeFloatClickListener(floatClickListener: FloatViewPlayListener) { listeners.remove(floatClickListener) } interface FloatViewPlayListener { fun onPauseClick() fun onStartClick() fun onPlayFinish() } internal inner class MyHandler : Handler() { override fun handleMessage(msg: Message) { when (msg.what) { UPDATE_VIEW_STATE -> updatePlayState() UPDATE_VIEW_COMPLETE -> { updatePlayState() for (listener in listeners) { //数据重新设置回调 listener.onPlayFinish() } } UPDATE_PLAY_TIME -> { updatePlayTime() } } } } }