จะส่งเหตุการณ์ onClick ของมุมมองไปยังผู้ปกครองบน ​​Android ได้อย่างไร


100

ฉันมี TextView ในเค้าโครงที่พื้นหลังเป็นตัวเลือก และข้อความของ TextView ถูกตั้งค่าเป็น Spanned จาก HTML จากนั้นฉันตั้งค่า TextView ด้วย LinkMovementMethod

ตอนนี้เมื่อฉันแตะที่ TextView เหตุการณ์การคลิกจะไม่ถูกส่งไปยังเค้าโครงหลักเพื่อเรียกใช้ตัวเลือก

ควรแก้ไขอย่างไร?

คำตอบ:


45

ฉันคิดว่าคุณต้องใช้หนึ่งในวิธีการเหล่านั้นเพื่อที่จะสามารถสกัดกั้นเหตุการณ์ก่อนที่มันจะถูกส่งไปยังส่วนประกอบที่เหมาะสม:

Activity.dispatchTouchEvent(MotionEvent) - สิ่งนี้ช่วยให้กิจกรรมของคุณสกัดกั้นเหตุการณ์การสัมผัสทั้งหมดก่อนที่จะถูกส่งไปที่หน้าต่าง

ViewGroup.onInterceptTouchEvent(MotionEvent) - สิ่งนี้ช่วยให้ ViewGroup สามารถรับชมเหตุการณ์ที่ส่งไปยัง View ย่อยได้

ViewParent.requestDisallowInterceptTouchEvent(boolean) - เรียกสิ่งนี้ตามมุมมองหลักเพื่อระบุว่าไม่ควรขัดขวางเหตุการณ์การสัมผัสด้วย onInterceptTouchEvent (MotionEvent)

ข้อมูลเพิ่มเติมที่นี่

หวังว่าจะช่วยได้


1
มีวิธีที่ง่ายกว่าในการส่งผ่านเหตุการณ์เพื่อทริกเกอร์ onClick และ onLongClick ในมุมมองผู้ปกครองหรือฉันต้องติดตั้งด้วยตัวเอง
shiami

ลองดูสิ่งนี้: stackoverflow.com/questions/2136696/pass-event-to-parent-view เป็นไปได้ว่าคุณอาจต้องการลองส่งตัวฟังการคลิกเดียวกันไปยังอินสแตนซ์อื่น ๆ ตามที่แนะนำแม้ว่าฉันจะไม่รู้ว่าจะใช้งานได้หรือไม่ แต่อาจคุ้มค่าที่จะลอง
Luis Miguel Serrano

คำตอบด้านล่างนี้สะอาดกว่ามาก
JPM

ฉันควรสร้างอินสแตนซ์ MotionEvent หรือไม่ ได้โปรดอธิบาย @LuisMiguelSerrano
olegario

@olegario โดยทั่วไปคุณจะกำหนดวิธีการใหม่สำหรับ dispatchTouchEvent โดยใช้ @Override เพื่อกำหนดพฤติกรรมใหม่ดังนั้นคุณเพียงแค่ได้รับเหตุการณ์การเคลื่อนไหวที่ระบบจัดเตรียมไว้ให้กับกิจกรรมของคุณ (หรือส่วนประกอบอื่นของแอปพลิเคชันของคุณ) และคุณ ปฏิบัติต่อและ / หรือส่งต่อไปยังส่วนประกอบเด็กจำนวนเท่าใดก็ได้ตามกฎของคุณเอง สิ่งที่ชอบ: @Override public boolean dispatchTouchEvent(MotionEvent ev) { ... }
Luis Miguel Serrano

214

ประกาศของคุณTextViewไม่สามารถคลิกได้ / สามารถโฟกัสโดยใช้android:clickable="false"และandroid:focusable="false"หรือและv.setClickable(false) v.setFocusable(false)เหตุการณ์การคลิกควรถูกส่งไปยังTextViewผู้ปกครองของตอนนี้

บันทึก:

เพื่อให้บรรลุนี้parentคุณต้องเพิ่มคลิกโดยตรง หรือการตั้งค่า android:clickable="false"และandroid:focusable="false"ไปยังผู้ปกครองโดยตรงที่จะผ่านไปยังผู้ปกครองฟังต่อไป


1
โอ้มนุษย์ถ้าฉันสามารถให้ +100 นี้ฉันจะ พยายามหาวิธีทำให้การคลิกใช้งานได้เฉพาะใน ViewPager และไม่ได้อยู่ในโครงร่างอะแดปเตอร์ด้วย TouchImageView ที่ใช้ onTouch! การแก้ปัญหานี้ทำงานได้อย่างมีเสน่ห์
JPM

1
แต่ถ้าฉันต้องการจัดการกับเหตุการณ์การเปลี่ยนโฟกัสของ EditText ล่ะ?
SweetWisher ツ

2
สถานการณ์คือ: ฉันมีเค้าโครงที่มีข้อความแก้ไขเลย์เอาต์สัมพัทธ์สปินเนอร์และมุมมองรายการ ฉันต้องการยิงเหตุการณ์สัมผัสของเลย์เอาต์หลักเมื่อใดก็ตามที่ฉันสัมผัสที่ใดก็ได้บน screenex ยกเว้นข้อความแก้ไขและสปินเนอร์
SweetWisher ツ

9
สิ่งสำคัญที่ต้องจำไว้ก็คือถ้าคุณใช้TextView#setOnClickListener()บนTextViewมันจะกลายเป็นคลิกได้แม้ว่าจะประกาศเป็นandroid:clickable="false"และแม้ว่าClickListenerจะตั้งค่าเป็นnull( setOnclickListener(null)) ก็ตาม
Christian García

3
ข้อเท็จจริงที่น่าสนใจ: หากใน TextView มีandroid:inputTypeแอตทริบิวต์มันจะใช้เหตุการณ์การคลิกอย่างเงียบ ๆ แม้จะมี clickable: false & focusable: false; ในกรณีของฉันมันถูกจัดวางอย่างมีสไตล์และฉันใช้เวลา 30 นาทีในการหาสาเหตุ
Kirill Karmazin

18

บางครั้งสิ่งนี้ช่วยได้:

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

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

ตัวแปรอื่นไม่ได้ผลเสมอไป:

child.setOnClickListener(null);

นี้ทำงานให้CardViewเป็นมุมมองของเด็กตั้งแต่CardViewดูเหมือนจะไม่สนใจและclickable="false" focusable="false"อย่างไรก็ตามการใช้setOnTouchListenerและโทรหาonTouchEventผู้ปกครองแทนทำให้ผู้ปกครองสามารถแสดงผลตอบรับการสัมผัสได้ (เช่นเอฟเฟกต์ระลอกคลื่น)
นาม

ผมโพสต์รหัสที่เกี่ยวข้องดังต่อไปนี้: stackoverflow.com/a/52928884/5652513
นาม

10

ใส่

android:duplicateParentState="true"

ในลูกจากนั้นมุมมองจะได้รับสถานะที่ดึงได้ (เน้นกด ฯลฯ ) จากผู้ปกครองโดยตรงแทนที่จะเป็นจากตัวมันเอง คุณสามารถตั้งค่า onclick สำหรับผู้ปกครองและเรียกเมื่อเด็กคลิก


OP ต้องการเรียกผู้ฟังคลิกของผู้ปกครองเมื่อเด็กถูกคลิกไม่ใช่ในทางกลับกันอย่างชาญฉลาด
Farid

3

หากคุณTextViewสร้างปัญหาในการคลิกให้ลบออกandroid:inputType=""จากไฟล์ xml ของคุณ


ถ้าคุณไม่รู้ว่าทำไมฉันขอแนะนำให้คุณอย่าทำ แค่บอกว่า ... กับเขาแต่ละคน
dell116

คุณควรตั้งค่าเป็นandroid:inputType="none"
AZ_

1

คำตอบนี้คล้ายกับคำตอบของ Alexander Ukhovยกเว้นว่าจะใช้เหตุการณ์การสัมผัสมากกว่าเหตุการณ์การคลิก เหตุการณ์เหล่านั้นอนุญาตให้พาเรนต์แสดงสถานะการกดที่เหมาะสม (เช่นเอฟเฟกต์ระลอกคลื่น) คำตอบนี้ยังอยู่ใน Kotlin แทน Java

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

0

หากคุณต้องการทั้งคู่OnTouchและOnClickฟังผู้ปกครองและเด็กดูทั้งคู่โปรดใช้เคล็ดลับด้านล่าง:

  1. User ScrollView เป็นมุมมองผู้ปกครองและภายในที่วางมุมมองลูกของคุณไว้ใน Relative / LinearLayout

  2. ทำให้ Parent ScrollView android:fillViewport="true"เพื่อไม่ให้เลื่อนดู

  3. จากนั้นตั้งค่าOnTouchผู้ฟังเป็นผู้ปกครองและOnClickผู้ฟังเป็นมุมมองเด็ก และเพลิดเพลินกับการโทรกลับของผู้ฟังทั้งสอง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.