Ý nghĩa của giá trị boolean được trả về từ một phương thức xử lý sự kiện trong Android


110

Trong android, hầu hết các phương thức xử lý sự kiện đều trả về giá trị boolean. Giá trị true / false đó có nghĩa là gì? nó sẽ dẫn đến những gì cho các sự kiện tiếp theo?

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

Về ví dụ trên, nếu trả về true trong phương thức onTouch , tôi thấy mọi sự kiện chạm (XUỐNG, LÊN, DI CHUYỂN, v.v.) đã được ghi lại theo logView của tôi . Ngược lại, nếu trả về false, một trong những sự kiện DOWN được ghi lại. Vì vậy, có vẻ như trả về false sẽ ngăn sự kiện lan truyền. Tôi có đúng không?

Hơn nữa, trong OnGestureListener , nhiều phương thức cũng phải trả về giá trị boolean. Chúng có cùng ý nghĩa không?

Câu trả lời:


140

Nếu bạn trở về truetừ một ACTION_DOWNsự kiện, bạn quan tâm đến phần còn lại của các sự kiện trong cử chỉ đó. "Cử chỉ" trong trường hợp này có nghĩa là tất cả các sự kiện cho đến trận chung kết ACTION_UPhoặc ACTION_CANCEL. Quay trở lại falsetừ một ACTION_DOWNnghĩa là bạn không muốn sự kiện và các quan điểm khác sẽ có cơ hội xử lý nó. Nếu bạn có các chế độ xem chồng chéo, đây có thể là chế độ xem anh chị em. Nếu không nó sẽ bong bóng đến cha mẹ.


3
adamp, có cách nào để tiếp tục nhận các sự kiện VÀ cho phép các sự kiện diễn ra không?
ticofab

@ticofab không, chỉ một chế độ xem gốc của chế độ xem hiện đang nhận các sự kiện mới có thể chặn các sự kiện trong tương lai trong cử chỉ. (Tất nhiên, bạn luôn có thể xây dựng hệ thống chuyển hướng của riêng mình trong chế độ xem dành cho cha mẹ, nhưng tôi sẽ không khuyên bạn nên làm như vậy trừ khi bạn thực sự biết mình đang làm gì. :))
adamp

@adamp Tôi không thể nghĩ ra lý do tại sao onTouch được gọi 2 lần khi trả về true và 1 lần chỉ khi trả về false.
Bhargav Jhaveri

1
@adamp: Tôi trả về false từ ACTION_DOWN nhưng ACTION_UP của tôi đang được kích hoạt và thực thi.
Mahantesh M Ambi

Tôi nhận được câu trả lời này sai hay mọi người khác ... Câu trả lời này nói rằng trả về true có nghĩa là sự kiện khó khăn không được tiêu thụ. Nhưng sự thật hoàn toàn ngược lại.
Kai Wang


12

Giá trị boolean xác định xem sự kiện có được sử dụng hay không.

Vâng, bạn chính xác. Nếu bạn trả về false, người nghe tiếp theo sẽ xử lý sự kiện. Nếu nó trả về true, sự kiện sẽ được trình nghe của bạn sử dụng và không được gửi đến phương thức tiếp theo.


2
Điều này là sai. truecó nghĩa là bạn đã sử dụng sự kiện và muốn phần còn lại của các sự kiện trong cử chỉ - người nghe / chế độ xem khác sẽ không nhận được sự kiện. falsecó nghĩa là để người khác xử lý sự kiện. Nó thực sự cụ thể hơn một chút; xem câu trả lời của tôi.
adamp 21/09/10

Làm thế nào đó không phải là chính xác những gì tôi đã nói?
Falmarri

1
Những gì bạn nói đã bị đảo ngược. :)
adamp 22/09/10

4

Tất cả các câu trả lời trên đều đúng nhưng kết quả là khác nhau nếu View có clickablehay khôngclickable

Ví dụ , tôi có một LinearLayoutchứa 1 Buttonvà 1 TextViewnhư thế này

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

Trong Hoạt động, tôi có mã như

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

Trường hợp 1 Linear onTouch return **FALSE**, Button onTouch return **FALSE**,TextView onTouch return **FALSE**

Nhấp vào nút

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

Nhấp vào TextView

TAG: TextView onTouch eventDOWN
TAG: LinearLayout onTouch eventDOWN

Nhấp vào LinearLayout

TAG: LinearLayout onTouch eventDOWN

Trường hợp 2 Linear onTouch return **FALSE**, Button onTouch return **TRUE**,TextView onTouch return **TRUE**

Nhấp vào nút

Similar to case 1

Nhấp vào TextView

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

Nhấp vào LinearLayout

Similar to case 1

Trường hợp 3 Linear onTouch return **TRUE**, Button onTouch return **FALSE**,TextView onTouch return **FALSE**

Nhấp vào nút

Similar to case 1

Nhấp vào TextView

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

Nhấp vào LinearLayout

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

Ghi chú

  • Mặc định TextViewnot clickable, nó sẽ trở nên có thể nhấp được nếu chúng ta đặt android:clickable="true"trong xml HOẶC khi chúng ta đặttextView.setOnClickListener(...)
  • Khi bạn gỡ lỗi, event MOVEcó thể gọi nhiều hơn nhật ký của tôi (nó dựa trên cách bạn chạm vào)

Tóm lược

  • onTouchtrả lại truehoặc xem là clickable , View sẽ nhận tất cả onTouchEvent
  • onTouchquay lại falsevà xem thì không clickable, chế độ xem sẽ không nhận được NEXT onTouchEvent (cha mẹ của nó có thể nhận được)

Hy vọng nó sẽ giúp
DEMO


1
Đây nên là câu trả lời! Cảm ơn bạn đã giải thích chi tiết như vậy
Mysterious_android

1

Tôi đã mất gần một ngày trong việc khắc phục sự cố, nhưng tôi vẫn phát hiện ra rằng hàm onTouch của tôi được gọi 2 lần khi sử dụng true và 1 lần khi sử dụng false.


Bạn có thể tìm ra lý do?
Bhargav Jhaveri

kiểm tra event.getAction()bởi vì nếu bạn trở falsevề sự kiện ACTION_DOWN, sự kiện ACTION_UP được bỏ qua bởi người nghe
doodeec

0

Từ Android-document :

Lưu ý: Android sẽ gọi các trình xử lý sự kiện trước rồi đến các trình xử lý mặc định thích hợp từ định nghĩa lớp thứ hai. Như vậy, việc trả về true từ các trình xử lý sự kiện này sẽ ngừng truyền sự kiện đến các trình xử lý sự kiện khác và cũng sẽ chặn lệnh gọi lại trình xử lý sự kiện mặc định trong Dạng xem. Vì vậy, hãy chắc chắn rằng bạn muốn kết thúc sự kiện khi bạn trả về true.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.