Apa arti nilai boolean yang dikembalikan dari metode penanganan peristiwa di Android

110

Di android, sebagian besar metode event listener mengembalikan nilai boolean. Apa arti nilai benar / salah itu? apa yang akan menghasilkan peristiwa selanjutnya?

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

Sehubungan dengan contoh di atas, jika return true dalam metode onTouch , saya menemukan setiap peristiwa sentuh (BAWAH, ATAS, PINDAH, dll) telah ditangkap sesuai dengan logView saya . Sebaliknya, jika return false, hanya peristiwa TURUN yang ditangkap. Jadi tampaknya pengembalian salah akan mencegah acara menyebar. Apakah saya benar ?

Selain itu, dalam OnGestureListener , banyak metode harus mengembalikan nilai boolean juga. Apakah mereka memiliki arti yang sama?

John Wang
sumber

Jawaban:

140

Jika Anda kembali truedari suatu ACTION_DOWNacara, Anda tertarik dengan acara lainnya dalam gerakan itu. "Isyarat" dalam hal ini berarti semua acara sampai final ACTION_UPatau ACTION_CANCEL. Kembali falsedari ACTION_DOWNcara yang Anda tidak ingin acara tersebut dan pandangan lain akan memiliki kesempatan untuk menanganinya. Jika Anda memiliki tampilan yang tumpang tindih, ini bisa menjadi tampilan saudara. Jika tidak, itu akan meluap ke induknya.

adamp
sumber
3
adamp, apakah ada cara untuk terus menerima peristiwa DAN membiarkan peristiwa itu lewat?
ticofab
@ticofab tidak, hanya induk dari tampilan yang saat ini menerima peristiwa yang dapat mencegat acara mendatang dalam isyarat. (Tentu saja, Anda selalu dapat membangun sistem pengalihan Anda sendiri dalam tampilan induk, tetapi saya tidak akan merekomendasikannya kecuali Anda benar-benar tahu apa yang Anda lakukan. :))
adamp
@adamp Saya tidak dapat memikirkan alasan mengapa onTouch dipanggil 2 kali ketika mengembalikan true dan 1 kali hanya ketika saya mengembalikan false.
Bhargav Jhaveri
1
@adamp: Saya mengembalikan false dari ACTION_DOWN tetapi ACTION_UP saya dipicu dan dijalankan.
Mahantesh M Ambi
Apakah saya mendapatkan balasan ini salah atau orang lain adalah ... Balasan ini mengatakan bahwa pengembalian benar berarti acara sulit tidak dikonsumsi. Tetapi kebenaran sepenuhnya terbalik.
Kai Wang
12

Nilai boolean menentukan apakah acara tersebut dikonsumsi atau tidak.

Ya, Anda benar. Jika Anda mengembalikan false, pendengar berikutnya akan menangani acara tersebut. Jika mengembalikan nilai true, peristiwa tersebut dikonsumsi oleh pendengar Anda dan tidak dikirim ke metode selanjutnya.

Falmarri
sumber
2
Ini salah. trueberarti Anda mengonsumsi acara dan menginginkan sisa acara dalam isyarat - pendengar / tampilan lain tidak akan menerima acara tersebut. falseberarti biarkan orang lain menangani acara tersebut. Ini sebenarnya sedikit lebih spesifik dari itu; lihat jawabanku.
adamp
Bagaimana tidak persis seperti yang saya katakan?
Falmarri
1
Apa yang Anda katakan terbalik. :)
adamp
4

Semua jawaban di atas benar tetapi hasilnya berbeda jika Lihat clickableatau tidakclickable

Contoh , saya punya LinearLayoutberisi 1 Buttondan 1 TextViewseperti ini

<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>

Dalam Aktivitas, saya memiliki kode suka

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"
        }
    }
}

Kasus 1 Linear onTouch return **FALSE**, Button onTouch return **FALSE**,TextView onTouch return **FALSE**

Klik pada Tombol

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

Klik pada TextView

TAG: TextView onTouch eventDOWN
TAG: LinearLayout onTouch eventDOWN

Klik LinearLayout

TAG: LinearLayout onTouch eventDOWN

Kasus 2 Linear onTouch return **FALSE**, Button onTouch return **TRUE**,TextView onTouch return **TRUE**

Klik pada Tombol

Similar to case 1

Klik pada TextView

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

Klik LinearLayout

Similar to case 1

Kasus 3 Linear onTouch return **TRUE**, Button onTouch return **FALSE**,TextView onTouch return **FALSE**

Klik pada Tombol

Similar to case 1

Klik pada TextView

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

Klik LinearLayout

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

Catatan

  • Default-nya TextViewadalah not clickable, itu akan menjadi dapat diklik jika kita set android:clickable="true"di xml OR saat kita settextView.setOnClickListener(...)
  • Ketika Anda men-debug, event MOVEdapat memanggil lebih dari log saya (itu berdasarkan bagaimana Anda mengetuk)

Ringkasan

  • onTouchkembali trueatau lihat clickable , View akan menerima semua onTouchEvent
  • onTouchkembali falsedan tampilan tidak clickable, tampilan tidak akan menerima onTouchEvent BERIKUTNYA (itu orang tua mungkin menerimanya)

Semoga membantu
DEMO

Phan Van Linh
sumber
1
Ini harus menjadi jawabannya! Terima kasih atas penjelasan mendetail
Mysterious_android
1

Saya kehilangan hampir satu hari dalam pemecahan masalah, masih saya menemukan, bahwa fungsi onTouch saya dipanggil 2 kali saat menggunakan true dan 1 kali saat menggunakan false.

kamor
sumber
Bisakah Anda menemukan alasannya?
Bhargav Jhaveri
periksa event.getAction()karena jika Anda kembali falsepada acara ACTION_DOWN, acara ACTION_UP diabaikan oleh pendengar
doodeec
0

Dari Android-document :

Catatan: Android akan memanggil penangan kejadian terlebih dahulu, kemudian penangan default yang sesuai dari definisi kelas kedua. Dengan demikian, mengembalikan true dari event listener ini akan menghentikan penyebaran event ke event listener lain dan juga akan memblokir callback ke event handler default di View. Jadi, pastikan Anda ingin menghentikan acara saat mengembalikan true.

Huy Nguyen
sumber