Làm cách nào để chuyển sự kiện onClick của một lượt xem cho cha mẹ của nó trên Android?


100

Tôi có một TextView trong một bố cục, nền của nó là một Selector. Và văn bản của TextView được đặt thành Spanned from HTML. Sau đó, tôi đặt TextView bằng LinkMovementMethod.

Bây giờ khi tôi nhấn vào TextView, sự kiện nhấp chuột không được gửi đến bố cục mẹ của nó để kích hoạt bộ chọn.

Điều này nên được giải quyết như thế nào?

Câu trả lời:


45

Tôi nghĩ rằng bạn cần sử dụng một trong những phương pháp đó để có thể chặn sự kiện trước khi nó được gửi đến các thành phần thích hợp:

Activity.dispatchTouchEvent(MotionEvent) - Điều này cho phép Hoạt động của bạn chặn tất cả các sự kiện chạm trước khi chúng được gửi đến cửa sổ.

ViewGroup.onInterceptTouchEvent(MotionEvent) - Điều này cho phép một ViewGroup xem các sự kiện khi chúng được chuyển đến các View con.

ViewParent.requestDisallowInterceptTouchEvent(boolean) - Gọi điều này khi một Chế độ xem gốc để chỉ ra rằng nó không nên chặn các sự kiện chạm bằng onInterceptTouchEvent (MotionEvent).

Thông tin thêm tại đây .

Hy vọng rằng sẽ giúp.


1
Có cách nào dễ dàng hơn để chuyển các sự kiện để kích hoạt onClick và onLongClick trong chế độ xem gốc hay tôi phải tự triển khai chúng?
shiami

Kiểm tra điều này: stackoverflow.com/questions/2136696/pass-event-to-parent-view Có thể bạn muốn thử chuyển cùng một trình nghe nhấp chuột sang các trường hợp khác như được đề xuất, mặc dù tôi không biết liệu nó có hoạt động không , nhưng có thể đáng để thử.
Luis Miguel Serrano

Câu trả lời dưới đây rõ ràng hơn nhiều
JPM

Tôi có nên khởi tạo MotionEvent không? Vui lòng giải thích, @LuisMiguelSerrano
olegario,

@olegario, thông thường, bạn xác định lại phương thức, ví dụ như cho sendTouchEvent, với @Override, để xác định một hành vi mới cho nó, vì vậy bạn chỉ nhận được một sự kiện chuyển động mà hệ thống đã cung cấp cho hoạt động của bạn (hoặc một thành phần khác của ứng dụng của bạn), và bạn xử lý nó và / hoặc chuyển tiếp đến bất kỳ số lượng thành phần con nào theo quy tắc của riêng bạn. Một cái gì đó như: @Override public boolean dispatchTouchEvent(MotionEvent ev) { ... }
Luis Miguel Serrano

212

Khai báo TextViewkhông thể nhấp / có thể lấy tiêu điểm của bạn bằng cách sử dụng android:clickable="false"android:focusable="false"hoặc v.setClickable(false)v.setFocusable(false). Các sự kiện nhấp chuột sẽ được gửi đến TextViewphụ huynh của ngay bây giờ.

Ghi chú:

Để đạt được điều này , bạn phải thêm nhấp chuột vào trực tiếp của nó parent. hoặc thiết lập android:clickable="false"và đặt android:focusable="false"cho cha mẹ trực tiếp của nó để chuyển người nghe cho cha mẹ khác .


1
Ôi trời, nếu tôi có thể cho tôi +100 cái này. Bạn đang cố gắng tìm ra cách làm cho một lần nhấp chỉ hoạt động trong ViewPager chứ không phải trong bố cục bộ điều hợp với TouchImageView triển khai onTouch! Giải pháp này hoạt động như một sự quyến rũ.
JPM

1
nhưng nếu tôi muốn xử lý sự kiện thay đổi Tiêu điểm của EditText thì sao?
SweetWisher ツ

2
Tình huống là: Tôi có một bố cục chứa văn bản chỉnh sửa, bố cục tương đối, con quay và chế độ xem danh sách. Tôi muốn kích hoạt sự kiện cảm ứng của bố cục mẹ bất cứ khi nào tôi chạm vào bất kỳ đâu trên màn hình, chấp nhận văn bản chỉnh sửa và trình quay
SweetWisher ツ

9
Một điều quan trọng cần lưu ý là nếu bạn sử dụng TextView#setOnClickListener()trên TextView, nó sẽ có thể nhấp được, ngay cả khi nó được khai báo là android:clickable="false", và ngay cả khi ClickListenernó được đặt thành null( setOnclickListener(null))
Christian García

3
Sự thật thú vị: nếu trong TextView có một android:inputTypethuộc tính, nó sẽ âm thầm tiêu thụ các sự kiện nhấp chuột ngay cả với clickable: false & focusable: false; trong trường hợp của tôi, nó đã được thiết lập theo một phong cách và tôi mất 30 phút để tìm ra nguyên nhân.
Kirill Karmazin

18

Đôi khi chỉ điều này giúp:

View child = parent.findViewById(R.id.btnMoreText);
    child.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            View parent = (View) v.getParent();
            parent.performClick();
        }
    });

Một biến thể khác, không phải lúc nào cũng hoạt động:

child.setOnClickListener(null);

Điều này làm việc cho CardViewchế độ xem trẻ em, vì CardViewdường như bỏ qua clickable="false"focusable="false". Tuy nhiên, thay vào đó , việc sử dụng setOnTouchListenervà gọi onTouchEventphụ huynh cho phép phụ huynh hiển thị phản hồi chạm (ví dụ: hiệu ứng gợn sóng).
methodignature 22/10/18

Tôi đã đăng mã có liên quan bên dưới: stackoverflow.com/a/52928884/5652513 .
methodignature 22/10/18

10

Đặt

android:duplicateParentState="true"

trong con thì các khung nhìn nhận được trạng thái có thể vẽ của nó (tập trung, nhấn, v.v.) từ cha trực tiếp của nó thay vì từ chính nó. bạn có thể đặt onclick cho cha mẹ và nó gọi khi con được nhấp


OP muốn gọi trình nghe nhấp chuột của cha mẹ khi con được nhấp, không phải ngược lại.
Farid

3

Nếu sự TextViewcố nhấp chuột tạo của bạn , thay vì xóa android:inputType=""khỏi tệp xml của bạn.


Nếu bạn không biết tại sao, tôi khuyên bạn không nên làm điều đó. Chỉ nói ... với mỗi người của mình.
dell116

Bạn nên đặt nó thànhandroid:inputType="none"
AZ_

1

Câu trả lời này tương tự như câu trả lời của Alexander Ukhov , ngoại trừ việc nó sử dụng sự kiện chạm thay vì sự kiện nhấp chuột. Những sự kiện đó cho phép cha mẹ hiển thị các trạng thái được ép thích hợp (ví dụ: hiệu ứng gợn sóng). Câu trả lời này cũng có trong Kotlin thay vì Java.

view.setOnTouchListener { view, motionEvent ->
    (view.parent as View).onTouchEvent(motionEvent)
}

0

Nếu bạn muốn cả người nghe OnTouchOnClickngười dùng xem cả phụ huynh và trẻ em, vui lòng sử dụng thủ thuật dưới đây:

  1. User ScrollView dưới dạng chế độ xem Cha và bên trong đã đặt chế độ xem con của bạn bên trong Relative / LinearLayout.

  2. Đặt android:fillViewport="true"Chế độ xem cuộn dành cho cha mẹ để Chế độ xem không bị cuộn.

  3. Sau đó, đặt OnTouchngười OnClicknghe thành chế độ xem gốc và người nghe thành Chế độ xem con. Và tận hưởng cả hai cuộc gọi lại của người nghe.

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.