事件分发机制:
首先,上代码和界面。
package net.jxvtc.advance001_event;
复制代码
import androidx.appcompat.app.AppCompatActivity;
复制代码
import android.annotation.SuppressLint;
复制代码
import android.os.Bundle;
复制代码
import android.view.MotionEvent;
复制代码
import android.view.View;
复制代码
import android.widget.Button;
复制代码
public class MainActivity extends AppCompatActivity {
复制代码
protected void onCreate(Bundle savedInstanceState) {
复制代码
super.onCreate(savedInstanceState);
复制代码
setContentView(R.layout.activity_main);
复制代码
btn_press=findViewById(R.id.btn_press);
复制代码
btn_press.setOnClickListener(new View.OnClickListener() {
复制代码
public void onClick(View v) {
复制代码
Log.d("TAG", "onClick: ");
复制代码
btn_press.setOnTouchListener(new View.OnTouchListener() {
复制代码
@SuppressLint("ClickableViewAccessibility")
复制代码
public boolean onTouch(View v, MotionEvent event) {
复制代码
Log.d("TAG", "onTouch: "+event.getAction());
复制代码
<?xml version="1.0" encoding="utf-8"?>
复制代码
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
复制代码
xmlns:app="http://schemas.android.com/apk/res-auto"
复制代码
xmlns:tools="http://schemas.android.com/tools"
复制代码
android:layout_width="match_parent"
复制代码
android:layout_height="match_parent"
复制代码
tools:context=".MainActivity">
复制代码
android:id="@+id/btn_press"
复制代码
android:layout_width="wrap_content"
复制代码
android:layout_height="wrap_content"
复制代码
app:layout_constraintBottom_toBottomOf="parent"
复制代码
app:layout_constraintLeft_toLeftOf="parent"
复制代码
app:layout_constraintRight_toRightOf="parent"
复制代码
app:layout_constraintTop_toTopOf="parent" />
复制代码
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
运行点击按钮后,日志输出为:
2021-03-13 20:13:33.490 7177-7177/net.jxvtc.advance001_event D/TAG: onTouch: 02021-03-13 20:13:33.612 7177-7177/net.jxvtc.advance001_event D/TAG: onTouch: 12021-03-13 20:13:33.649 7177-7177/net.jxvtc.advance001_event D/TAG: onClick:
如果修改上述的 Java 代码把 onTouch 方法中的
return false;改成 return true;
日志输出将变为:
2021-03-13 20:13:44.647 7357-7357/net.jxvtc.advance001_event D/TAG: onTouch: 02021-03-13 20:13:44.744 7357-7357/net.jxvtc.advance001_event D/TAG: onTouch: 1
为什么呢?
通过源码来找寻答案:
1、当点击 Button 时,首先会执行 View 的 dispatchTouchEvent 方法:
View.java
* Pass the touch screen motion event down to the target view, or this
复制代码
* view if it is the target.
复制代码
* @param event The motion event to be dispatched.
复制代码
* @return True if the event was handled by the view, false otherwise.
复制代码
public boolean dispatchTouchEvent(MotionEvent event) {
复制代码
if (onFilterTouchEventForSecurity(event)) {
复制代码
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
复制代码
//noinspection SimplifiableIfStatement
复制代码
ListenerInfo li = mListenerInfo; //这个具体见下面的代码,也不为空
复制代码
if (li != null && li.mOnTouchListener != null
复制代码
&& (mViewFlags & ENABLED_MASK) == ENABLED
复制代码
&& li.mOnTouchListener.onTouch(this, event)) {
复制代码
//如果onTouch返回true的话 result:true
复制代码
//如果result是false,则取决于onTouchEvent的取值,
复制代码
//如果上面onTouch返回的是false,并且onTouchEvent为true,则结果为true.
复制代码
if (!result && onTouchEvent(event)) {
复制代码
MainActivity.java
btn_press.setOnTouchListener(new View.OnTouchListener() {
复制代码
View.java
* Register a callback to be invoked when a touch event is sent to this view.
复制代码
* @param l the touch listener to attach to this view
复制代码
public void setOnTouchListener(OnTouchListener l) {
复制代码
getListenerInfo().mOnTouchListener = l;
复制代码
ListenerInfo getListenerInfo() {
复制代码
if (mListenerInfo != null) {
复制代码
mListenerInfo = new ListenerInfo();
复制代码
* Implement this method to handle touch screen motion events.
复制代码
* If this method is used to detect click actions, it is recommended that
复制代码
* the actions be performed by implementing and calling
复制代码
* {@link #performClick()}. This will ensure consistent system behavior,
复制代码
* <li>obeying click sound preferences
复制代码
* <li>dispatching OnClickListener calls
复制代码
* <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
复制代码
* accessibility features are enabled
复制代码
* @param event The motion event.
复制代码
* @return True if the event was handled, false otherwise.
复制代码
public boolean onTouchEvent(MotionEvent event) {
复制代码
if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
复制代码
case MotionEvent.ACTION_UP:
复制代码
if (mPerformClick == null) {
复制代码
mPerformClick = new PerformClick();
复制代码
if (!post(mPerformClick)) {
复制代码
mIgnoreNextUpEvent = false;
复制代码
* Entry point for {@link #performClick()} - other methods on View should call it instead of
复制代码
* {@code performClick()} directly to make sure the autofill manager is notified when
复制代码
* necessary (as subclasses could extend {@code performClick()} without calling the parent's
复制代码
private boolean performClickInternal() {
复制代码
// Must notify autofill manager before performing the click actions to avoid scenarios where
复制代码
// the app has a click listener that changes the state of views the autofill service might
复制代码
notifyAutofillManagerOnClick();
复制代码
public boolean performClick() {
复制代码
// We still need to call this method to handle the cases where performClick() was called
复制代码
// externally, instead of through performClickInternal()
复制代码
notifyAutofillManagerOnClick();
复制代码
final ListenerInfo li = mListenerInfo;
复制代码
if (li != null && li.mOnClickListener != null) {
复制代码
playSoundEffect(SoundEffectConstants.CLICK);
复制代码
li.mOnClickListener.onClick(this);//点击事件
复制代码
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
复制代码
notifyEnterOrExitForAutoFillIfNeeded(true);
复制代码
评论