自定义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 中处理长按抬起的操作
相关文章推荐
- pan手势监听对view的上下左右滑动,利用关联对象在block中触发view的点击事件(附手势大全)
- 安卓中RecyclerView的简单使用和自定义RecyclerView的接口点击监听事件
- AlertDialog中使用自定义View,view中的Button如何设置点击事件监听
- 5.轮播广告AndroidImageSlider的使用(包括自定义indicator,和sliderview的点击监听事件,架构分析)
- 自定义View(4)——用户交互、点击事件监听
- AlertDialog中使用自定义View,其中的Button如何设置点击事件监听
- Android 自定义View——自定义点击事件
- 自定义View及其监听事件
- 如何监听UIimageview的点击事件以及如何控制UIimageview显示圆形
- RecyclerView下拉刷新,左滑删除和项目点击事件的监听
- UIView加入手势 然后UITableView 加入进这个View 导致UITableView 的单元格点击事件无效
- 自定义View监听onKeyDown事件,View捕获焦点
- Android activity加入左右监听手势,页面是一个listview,不影响listview的点击事件
- 解决UITapGestureRecognizer手势与UITableView的点击事件的冲突
- IOS自定义View使用block实现点击事件
- android父View手势和子View的点击事件处理
- 自定义AutoCompleteTextView的点击事件
- recyclerView自定义点击事件
- 为 TextView 的部分文字设置超链接样式并监听点击事件
- android 自定义TextView中Html超链接点击事件详解