package com.quyunshuo.androidbaseframemvvm.common.util

import android.annotation.SuppressLint
import android.os.Handler
import android.view.MotionEvent
import android.view.View
import android.view.View.OnLongClickListener
import android.view.View.OnTouchListener
import kotlin.math.abs


/**
 * @author whw
 * @time 2019/3/6
 * @Description 长按事件监听
 */
object LongClickUtils {
    private const val TAG = "LongClickUtils"

    /**
     * 自定义时长的长按事件
     *
     * @param handler           外界handler(为了减少handler的泛滥使用,最好全局传handler引用,如果没有就直接传 new Handler())
     * @param longClickView     被长按的视图(任意控件)
     * @param delayMillis       长按时间,毫秒
     * @param longClickListener 长按回调的返回事件
     */
    fun setLongClick(
        handler: Handler,
        longClickView: View,
        delayMillis: Long,
        longClickListener: OnLongClickListener?
    ) {
        longClickView.setOnTouchListener(object : OnTouchListener {
            private val TOUCH_MAX = 50
            private var mLastMotionX = 0
            private var mLastMotionY = 0

            @SuppressLint("ClickableViewAccessibility")
            override fun onTouch(v: View, event: MotionEvent): Boolean {
                val x = event.x.toInt()
                val y = event.y.toInt()

                when (event.action) {
                    MotionEvent.ACTION_UP ->                         // 抬起时,移除已有Runnable回调,抬起就算长按了(不需要考虑用户是否长按了超过预设的时间)
                        handler.removeCallbacks(r)

                    MotionEvent.ACTION_MOVE -> if (abs((mLastMotionX - x).toDouble()) > TOUCH_MAX
                        || abs((mLastMotionY - y).toDouble()) > TOUCH_MAX
                    ) {
                        // 移动误差阈值
                        // xy方向判断
                        // 移动超过阈值，则表示移动了,就不是长按(看需求),移除 已有的Runnable回调
                        handler.removeCallbacks(r)
                    }

                    MotionEvent.ACTION_DOWN -> {
                        // 每次按下重新计时
                        // 按下前,先移除 已有的Runnable回调,防止用户多次单击导致多次回调长按事件的bug
                        handler.removeCallbacks(r)
                        mLastMotionX = x
                        mLastMotionY = y
                        // 按下时,开始计时
                        handler.postDelayed(r, delayMillis)
                    }
                }
                return true //onclick等其他事件不能用请改这里
            }

            private val r = Runnable { longClickListener?.onLongClick(longClickView) }
        })
    }
}