在android事件传递一般包括三个对象: Activity,ViewGroup,View,事件分发顺序为:Activity->ViewGroup->View,事件分发过程由
onTouchEvent()
onInterceptTouchEvent()
dispatchTouchEvent()
这三个方法协助完成, 其中View没有onInterceptTouchEvent()方法
下面用一个简单的例子进行说明:
mainLayout为自定义控件
class MainActivity : AppCompatActivity(), View.OnTouchListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//view没有onInterceptTouchEvent
//onTouch事件优于onClick
btnTest.setOnTouchListener(this)
btnTest.setOnClickListener {
Toast.makeText(this@MainActivity,"te", Toast.LENGTH_LONG).show()
}
}
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
when (v){
mainLayout->{
when (event?.action){
MotionEvent.ACTION_DOWN->{
Log.d("touch event","mainLayout ACTION_DOWN")
}
MotionEvent.ACTION_UP->{
Log.d("touch event","mainLayout ACTION_UP")
}
}
}
btnTest->{
when (event?.action){
MotionEvent.ACTION_DOWN->{
Log.d("touch event","btnTest ACTION_DOWN")
}
MotionEvent.ACTION_UP->{
Log.d("touch event","btnTest ACTION_UP")
}
}
}
}
return true
}
//activity的dispatchTouchEvent
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
//事件分派
when (ev?.action){
MotionEvent.ACTION_DOWN->{
Log.d("touch event","activity dispatchTouchEvent ACTION_DOWN")
//在ACTION_DOWN return true,子view收不到后面的事件
//return true
}
MotionEvent.ACTION_UP->{
Log.d("touch event","activity dispatchTouchEvent ACTION_UP")
//ACTION_UP return true,子view收不到ACTION_UP
//return true
}
}
return super.dispatchTouchEvent(ev)
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
return super.onTouchEvent(event)
}
}
我们通过log,每次touch btnTest或mainLayout,都会先打印Activity里的dispatchTouchEvent里的ACTION_DOWN,如果在dispatchTouchEvent里的ACTION_DOWN return true,子view就收不到事件传递了;
TestLayout里onInterceptTouchEvent,如果return true,表示中断传递给子view的事件
class TestLayout : ConstraintLayout{ constructor(mContext: Context) : super(mContext) { val context = mContext } constructor(mContext: Context, mAttributeSet: AttributeSet) : super(mContext, mAttributeSet) { val context = mContext } override fun onTouchEvent(event: MotionEvent?): Boolean { //return super.onTouchEvent(event) Log.d("touch event","view group") return true } override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean { //return super.onInterceptTouchEvent(ev) //true:中断事件 //中断后, TestLayout的子view btnTest的onTouch,onClick都不会执行 return true } override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { //事件分派 when (ev?.action){ MotionEvent.ACTION_DOWN->{ Log.d("touch event","view group dispatchTouchEvent ACTION_DOWN") //在ACTION_DOWN return true,子view收不到后面的事件 //return true } MotionEvent.ACTION_UP->{ Log.d("touch event","view group dispatchTouchEvent ACTION_UP") //ACTION_UP return true,子view收不到ACTION_UP //return true } } return super.dispatchTouchEvent(ev) } }