Что означает логическое значение, возвращаемое методом обработки событий в Android

110

В Android большинство методов прослушивателя событий возвращают логическое значение. Что означает это истинное / ложное значение? к чему это приведет к событиям подпоследовательности?

class MyTouchListener implements OnTouchListener {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        logView.showEvent(event);
        return true;
    }
}

Что касается приведенного выше примера, если return true в методе onTouch , я обнаружил, что каждое событие касания (DOWN, UP, MOVE и т.д.) было зафиксировано в соответствии с моим logView . Напротив, если return false, одно событие DOWN было захвачено. Похоже, что return false предотвратит распространение события. Я прав ?

Более того, в OnGestureListener многие методы также должны возвращать логическое значение. Имеют ли они то же значение?

Джон Ван
источник

Ответы:

140

Если вы вернетесь trueс ACTION_DOWNмероприятия, вас интересуют остальные события этого жеста. «Жест» в данном случае означает все события до финала ACTION_UPили ACTION_CANCEL. Возврат falseиз ACTION_DOWNсредства означает, что событие вам не нужно, и другие представления смогут его обработать. Если у вас есть перекрывающиеся представления, это может быть одноуровневое представление. В противном случае он будет пузыриться до родителя.

Адамп
источник
3
adamp, есть ли способ продолжать получать события И пропускать события?
ticofab 08
@ticofab нет, только родительский элемент представления, получающего события, может перехватывать будущие события в жесте. (Конечно, вы всегда можете создать свои собственные системы перенаправления в родительском представлении, но я бы не рекомендовал это, если вы действительно не знаете, что делаете. :))
adamp
@adamp Я не могу понять причину, по которой onTouch вызывается 2 раза при возврате истины и 1 раз только когда я возвращаю ложь.
Бхаргав Джавери
1
@adamp: я возвращаю false из ACTION_DOWN, но мой ACTION_UP запускается и выполняется.
Mahantesh M Ambi
Я получаю этот ответ неправильно или все остальные ... В этом ответе говорится, что return true означает, что сложное событие не используется. Но на самом деле все наоборот.
Кай Ван,
12

Логическое значение определяет, будет ли событие использовано или нет.

Да ты прав. Если вы вернете false, следующий слушатель обработает событие. Если он возвращает истину, событие обрабатывается вашим слушателем и не отправляется следующему методу.

Falmarri
источник
2
Это неправда. trueозначает, что вы использовали событие и хотите, чтобы остальные события были в жесте - другие слушатели / представления не получат события. falseозначает позволить кому-то другому обработать событие. На самом деле это немного более конкретно, чем это; увидеть мой ответ.
adamp
Как это не совсем то, что я сказал?
Falmarri
1
То, что вы сказали, перевернуто. :)
adamp
4

Все приведенные выше ответы верны, но результат отличается, если вид clickableили нетclickable

Например , у меня есть LinearLayout1 Buttonи 1, TextViewкак это

<LinearLayout
    android:id="@+id/linearlayout_root"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0aa"
    android:orientation="vertical">

    <Button
        android:id="@+id/button_click"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="40dp"
        android:text="Button Click"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/textview_click"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="40dp"
        android:text="TextView Click"
        android:textSize="20sp"
        android:background="#e4e4e4"
        />

</LinearLayout>

В Activity у меня есть код вроде

class MainActivity : AppCompatActivity() {
    val TAG = "TAG"

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        findViewById<LinearLayout>(R.id.linearlayout_root).setOnTouchListener { v, event ->
            Log.i(TAG, "LinearLayout onTouch event " + getDisplayAction(event.action))
            false
        }

        findViewById<Button>(R.id.button_click).setOnTouchListener { v, event ->
            Log.i(TAG, "Button onTouch event " + getDisplayAction(event.action))
            false
        }

        findViewById<TextView>(R.id.textview_click).setOnTouchListener { v, event ->
            Log.i(TAG, "TextView onTouch event " + getDisplayAction(event.action))
            false
        }
    }

    private fun getDisplayAction(action: Int): String {
        return when (action) {
            MotionEvent.ACTION_DOWN -> "DOWN"
            MotionEvent.ACTION_MOVE -> "MOVE"
            MotionEvent.ACTION_UP -> "UP"
            MotionEvent.ACTION_CANCEL -> "CANCEL"
            MotionEvent.ACTION_OUTSIDE -> "OUTSIDE"
            else -> "UNKNOWN"
        }
    }
}

Случай 1 Linear onTouch return **FALSE**, Button onTouch return **FALSE**,TextView onTouch return **FALSE**

Нажмите кнопку

I/TAG: Button onTouch eventDOWN
I/TAG: Button onTouch eventMOVE
I/TAG: Button onTouch eventUP

Нажмите на TextView

TAG: TextView onTouch eventDOWN
TAG: LinearLayout onTouch eventDOWN

Щелкните LinearLayout

TAG: LinearLayout onTouch eventDOWN

Случай 2 Linear onTouch return **FALSE**, Button onTouch return **TRUE**,TextView onTouch return **TRUE**

Нажмите кнопку

Similar to case 1

Нажмите на TextView

TAG: TextView onTouch event DOWN
TAG: TextView onTouch event MOVE
TAG: TextView onTouch event UP

Щелкните LinearLayout

Similar to case 1

Случай 3 Linear onTouch return **TRUE**, Button onTouch return **FALSE**,TextView onTouch return **FALSE**

Нажмите кнопку

Similar to case 1

Нажмите на TextView

TAG: TextView onTouch event DOWN
TAG: LinearLayout onTouch event DOWN
TAG: LinearLayout onTouch event MOVE
TAG: LinearLayout onTouch event UP

Щелкните LinearLayout

TAG: LinearLayout onTouch event DOWN
TAG: LinearLayout onTouch event MOVE
TAG: LinearLayout onTouch event UP

Заметка

  • Дефолт TextViewэто not clickable, он станет интерактивным , если положить android:clickable="true"в XML или когда мы устанавливаемtextView.setOnClickListener(...)
  • При отладке event MOVEможет вызывать больше, чем мой журнал (это зависит от того, как вы нажимаете)

Резюме

  • onTouchвозврат trueили просмотр clickable , просмотр получит все onTouchEvent
  • onTouchreturn falseи view нет clickable, view не получит NEXT onTouchEvent (его родитель может получить)

Надеюсь, это поможет
DEMO

Фан Ван Линь
источник
1
Это должен быть ответ! Спасибо за такое подробное объяснение
Mysterious_android
1

Я потерял почти один день на устранение неполадок, но я обнаружил, что моя функция onTouch вызывается 2 раза при использовании true и 1 раз при использовании false.

Камор
источник
Не могли бы вы узнать причину?
Бхаргав Джавери
проверьте, event.getAction()потому что, если вы вернетесь falseк событию ACTION_DOWN, событие ACTION_UP игнорируется слушателем
doodeec
0

Из документа Android :

Примечание: Android сначала вызовет обработчики событий, а затем соответствующие обработчики по умолчанию из определения класса. Таким образом, возвращение истины от этих прослушивателей событий остановит распространение события на другие прослушиватели событий, а также заблокирует обратный вызов обработчику событий по умолчанию в представлении. Поэтому убедитесь, что вы хотите прекратить событие, когда вернете true.

Хай Нгуен
источник