您的位置:首页 > 其它

自定义view的点击、长按、及长按手势监听事件

2017-09-05 12:02 483 查看
package com.dashen.xinyi.view.ui

import android.annotation.SuppressLint
import android.app.Dialog
import android.content.Context
import android.os.*
import android.util.AttributeSet
import android.util.Log
import android.view.*
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.apkfuns.logutils.LogUtils
import com.dashen.xinyi.R
/**
*
* 项目名称:  Uranus-Android
* 包名:     com.dashen.xinyi.view.ui
* 创建人 :   whj
* 创建时间:  2017/9/1 16:13
* 类描述:    自定义语音按钮样式
* 备注:
**/
@SuppressLint("NewApi")
class RecordButtonSpecial : ImageView, GestureDetector.OnGestureListener {
private var tvDec: TextView? = null
    private var ivWarn: ImageView? = null
    private var ivVolume: ImageView? = null
    private var llStandard: LinearLayout? = null
    private var recordDialog: Dialog? = null
    private var thread: ObtainDecibelThread? = null
    private var volumeHandler: Handler? = null
    private var y: Float ? = 0.toFloat()
private var isLongClick=false//是否已判断为长按
private var isCountTimer=false//是否10s倒计时

private var decibel:Int=0
private var detector: GestureDetector? = null
    private var onButtonEventListener: OnButtonEventListener? = null
    companion object {
private var startTime: Long = 0
private val res = intArrayOf(R.mipmap.icon_volume_1, R.mipmap.icon_volume_2, R.mipmap.icon_volume_3, R.mipmap.icon_volume_4, R.mipmap.icon_volume_5, R.mipmap.icon_volume_6, R.mipmap.icon_volume_7)
val MAX_TIME = 60 * 1000 + 500// 1分钟,最长
//        private val MIN_INTERVAL_TIME = 1 * 1000// 1s 最短
//        var File_Voice = Environment.getExternalStorageDirectory().path + "/com.dashen.xinyi/voice"// 录音全部放在这个目录下
}

constructor(context: Context) : super(context) {
init()
}

constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
init()
}

constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init()
}

@SuppressLint("HandlerLeak")
private fun init() {
detector=GestureDetector(this)
volumeHandler = object : Handler() {
override fun handleMessage(msg: Message) {
when(msg.what){
-100->{ stopRecording() }
else->{
if(msg.what != -1&&ivVolume!=null){
ivVolume!!.setImageResource(res[msg.what])
}
}
}
}
}
}

@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent): Boolean {
detector!!.onTouchEvent(event)
val action = event.action
y = event.y
if (llStandard != null && y!! < 0) {
//// TODO: 2017/5/22 取消录音
llStandard!!.visibility = View.GONE
ivWarn!!.visibility = View.VISIBLE
ivWarn!!.setImageResource(R.mipmap.icon_dialog_cancel)
tvDec!!.text = "松开手指,取消发送"
} else if (llStandard != null) {
llStandard!!.visibility = View.VISIBLE
ivWarn!!.visibility = View.GONE
if (!isCountTimer){ tvDec!!.text = "手指上滑,取消发送" }
}
//        Log.e("MotionEvent","onTouchEvent------->X:"+event.x+"---Y:"+event.y)
when (action) {
MotionEvent.ACTION_DOWN -> {
isLongClick=false
initDialogAndStartRecord()//初始化计时 、dialog
Log.e("MotionEvent","ACTION_DOWN------->X:"+event.x+"---Y:"+event.y)
}
MotionEvent.ACTION_MOVE->{
Log.e("MotionEvent","ACTION_MOVE------->X:"+event.x+"---Y:"+event.y)
}
MotionEvent.ACTION_UP -> {
Log.e("MotionEvent","ACTION_UP------->X:"+event.x+"---Y:"+event.y)
startTimer.cancel() // 主动松开时取消计时
recordTimer.cancel() // 主动松开时取消计时
isCountTimer=false
                if (isLongClick){//长按事件 结果是取消还是正常
if (y!! >= 0) {//这里要注意 当System.currentTimeMillis() - startTime = MAX_TIME时 dialog消息 录音结束
//TODO 结束事件  添加结束事件回调监听  出结果
finishRecord()
} else if (y !!< 0) {  //当手指向上滑,会cancel
//TODO 手上滑 取消   添加取消事件回调监听  取消
cancelRcord()
if (onButtonEventListener!=null){ onButtonEventListener!!.onCancelRecordListener() }
}
}
isLongClick=false
}
MotionEvent.ACTION_CANCEL ->{// 异常
stopRecording()
}
}
return true
}

override fun onFling(p0: MotionEvent?, p1: MotionEvent?, p2: Float, p3: Float): Boolean {
Log.e("OnGesture-onFling->", "X:" + p0!!.x + "    Y:" + p0!!.x)
return false
}

override fun onScroll(p0: MotionEvent?, p1: MotionEvent?, p2: Float, p3: Float): Boolean {
Log.e("OnGesture-onScroll->", "X:" + p0!!.x + "    Y:" + p0!!.x)
return false
}

//    override fun onTouchEvent(event: MotionEvent?): Boolean {
//        detector!!.onTouchEvent(event)
//        return super.onTouchEvent(event)
//    }

override fun onDown(p0: MotionEvent?): Boolean {
//        Log.e("OnGesture-onDown->","X:"+ p0!!.x+"    Y:"+ p0!!.x)
isLongClick=false
        return false
}

override fun onShowPress(p0: MotionEvent?) {
Log.e("OnGesture-onShowPress->","X:"+ p0!!.x+"    Y:"+ p0!!.x)
}

override fun onSingleTapUp(p0: MotionEvent?): Boolean {//单击事件 onDown-》onSingleTapUp
Log.e("OnGesture-SingleTapUp->","X:"+ p0!!.x+"    Y:"+ p0!!.x)
isLongClick=false
//TODO 单击事件  添加单击事件回调监听
if (onButtonEventListener!=null){ onButtonEventListener!!.onClickListener2() }
return false
}

override fun onLongPress(p0: MotionEvent?) {//长按事件  onDown-》onShowPress-》onLongPress
Log.e("OnGesture-onLongPress->", "X:" + p0!!.x + "    Y:" + p0!!.x)
isLongClick=true
//TODO 长按事件  添加长按事件回调监听  即开始
startRecording()
if (onButtonEventListener!=null){ onButtonEventListener!!.onLongClickListener() }
}

/**
* 初始化录音对话框 并 开始录音
*/
private fun initDialogAndStartRecord() {
startTime = System.currentTimeMillis()
recordDialog = Dialog(context, R.style.chat_volume)
val dialogView = View.inflate(this.context, R.layout.dialog_volume, null)
recordDialog!!.setContentView(dialogView)
//音量
ivVolume = dialogView.findViewById(R.id.iv_volume)
//警告
ivWarn = dialogView.findViewById(R.id.iv_warn)
//描述
tvDec = dialogView.findViewById(R.id.tv_dec)
//标准录音view
llStandard = dialogView.findViewById(R.id.ll_standard)
//        recordDialog.setOnDismissListener(onDismiss);
//居中显示
val lp = recordDialog!!.window!!.attributes

lp.gravity = Gravity.CENTER
}

/**
* 放开手指,结束录音处理
*/
private fun finishRecord() {
stopRecording()
if (onButtonEventListener!=null){ onButtonEventListener!!.onFinishRecordListener() }
}

/**
* 执行录音操作
*/
private fun startRecording() {
//震动提醒
val vib = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vib.vibrate(100L)
startTimer.start()
//监测分贝
thread = ObtainDecibelThread()
thread!!.start()
recordDialog!!.show()
}

private fun stopRecording() {
if (thread != null) {
thread!!.exit()
thread = null
}
recordDialog!!.dismiss()
}

/**
* 取消录音对话框和停止录音
*/
fun cancelRcord() {
stopRecording()
}

/**
* 录音开始计时器,允许的最大时长倒数10秒时进入倒计时
*/
private val startTimer = object : CountDownTimer((MAX_TIME - 500 - 10000).toLong(), 1000) { // 60秒后开始倒计时
override fun onFinish() {
recordTimer.start()
}

override fun onTick(millisUntilFinished: Long) {}
}

/**
* 录音最后10秒倒计时器,倒计时结束发送录音
*/
private val recordTimer = object : CountDownTimer(10000+300, 1000) {
override fun onFinish() {
finishRecord()
isCountTimer=false
}

override fun onTick(millisUntilFinished: Long) { // 显示倒计时动画
isCountTimer=true
tvDec!!.text = "还可以说${millisUntilFinished.toInt() / 1000}秒"
Log.e("一分钟录音----》10s倒计时","倒计时:"+(millisUntilFinished.toInt() / 1000))
}
}

private inner class ObtainDecibelThread : Thread() {

@Volatile private var running = true
        fun exit() { running = false }

override fun run() {
while (running) {
//TODO  关联振幅
val db = getDecibel() //振幅  0-100
LogUtils.e("振幅值----原始----》"+db)
if (db != 0 && y!! >= 0) {//分7段  一段刻度14
//                    val db = (10 * Math.log(db.toDouble()) / Math.log(10.0)).toInt()
if (db < 14){
volumeHandler!!.sendEmptyMessage(0)
} else if (db < 28){
volumeHandler!!.sendEmptyMessage(1)
} else if (db < 42){
volumeHandler!!.sendEmptyMessage(2)
} else if (db < 56){
volumeHandler!!.sendEmptyMessage(3)
} else if (db < 70){
volumeHandler!!.sendEmptyMessage(4)
} else if (db < 84){
volumeHandler!!.sendEmptyMessage(5)
} else{
volumeHandler!!.sendEmptyMessage(6)
}
}

volumeHandler!!.sendEmptyMessage(-1)
if (System.currentTimeMillis() - startTime > MAX_TIME) {
finishRecord()
}
try {
Thread.sleep(200)
} catch (e: InterruptedException) {
e.printStackTrace()
}
}
}
}

//控件的事件监听
interface OnButtonEventListener{
fun onClickListener2()
fun onLongClickListener()
fun onCancelRecordListener()
fun onFinishRecordListener()
}

fun setOnButtonEventListener(onButtonEventListener:OnButtonEventListener){
this.onButtonEventListener=onButtonEventListener
}

fun setDecibel(decibel:Int){
this.decibel=decibel
}
fun getDecibel():Int{
return this.decibel
}
}

onDown:用户按下屏幕就会触发
onShowPress:如果是按下的时间超过瞬间,而且在按下的时候没有松开或者是拖动的,那么onShowPress就会执行
onSingleTapUp:一次单独的轻击抬起操作
onLongPress:长按触摸屏
onFling:快速移动后松开
onScroll:滑动(非按下移动)
onTouchEvent MotionEvent.ACTION_MOVE中处理长按上滑下滑手势操作
onTouchEvent MotionEvent.ACTION_UP 中处理长按抬起的操作
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: