ปุ่ม Android ได้เรียกใช้ setOnTouchListener แต่ไม่ได้ลบล้าง performClick


113

เมื่อฉันพยายามเพิ่มลงonTouchListner()ในปุ่มมันทำให้ฉันได้รับไฟล์

ปุ่มได้เรียกใช้ setOnTouchListener แต่ไม่ได้ลบล้าง performClick

คำเตือน. มีใครทราบวิธีแก้ไขบ้างครับ?

1

btnleftclick.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        return false;
    }
});

ข้อผิดพลาด:

มุมมองแบบกำหนดเองได้เรียกใช้ setOnTouchListener แต่ไม่ได้แทนที่ performClick หากมุมมองที่แทนที่ onTouchEvent หรือใช้ OnTouchListener จะไม่ใช้งาน performClick และเรียกมันเมื่อตรวจพบการคลิกมุมมองอาจไม่จัดการการกระทำการเข้าถึงอย่างถูกต้อง ตรรกะในการจัดการการคลิกควรวางไว้ใน View # performClick เนื่องจากบริการการเข้าถึงบางอย่างเรียกใช้ performClick เมื่อการดำเนินการคลิกเกิดขึ้น


มุมมองแบบกำหนดเองImageViewได้เรียกใช้ setOnTouchListener แต่ไม่ได้แทนที่ performClick หากมุมมองที่แทนที่ onTouchEvent หรือใช้ OnTouchListener จะไม่ใช้ performClick และเรียกมันเมื่อตรวจพบการคลิกมุมมองอาจไม่จัดการการดำเนินการการเข้าถึงอย่างถูกต้อง ตรรกะในการจัดการการคลิกควรวางไว้ใน View # performClick เนื่องจากบริการการเข้าถึงบางอย่างเรียกใช้ performClick เมื่อการดำเนินการคลิกเกิดขึ้น
kas

โปรดดูคำตอบของฉันที่นี่: stackoverflow.com/questions/47170075/…
lambda

คำตอบ:


134

คำเตือนนี้เกิดขึ้นเนื่องจาก Android ต้องการเตือนให้คุณนึกถึงคนตาบอดหรือผู้พิการทางสายตาที่อาจใช้แอปของคุณ ฉันขอแนะนำให้คุณดูวิดีโอนี้เพื่อดูภาพรวมคร่าวๆว่าเป็นอย่างไร

มุมมองมาตรฐาน UI (เช่นButton,TextViewฯลฯ ) มีการตั้งค่าทั้งหมดขึ้นเพื่อให้ผู้ใช้ตาบอดกับข้อเสนอแนะที่เหมาะสมผ่านบริการการเข้าถึง เมื่อคุณพยายามจัดการเหตุการณ์การสัมผัสด้วยตัวเองคุณกำลังตกอยู่ในอันตรายที่จะลืมให้ข้อเสนอแนะนั้น นี่คือสิ่งที่เตือนสำหรับ

ตัวเลือกที่ 1: สร้างมุมมองแบบกำหนดเอง

โดยปกติการจัดการเหตุการณ์การสัมผัสเป็นสิ่งที่ทำในมุมมองที่กำหนดเอง อย่าปิดตัวเลือกนี้เร็วเกินไป มันไม่ยากเลยจริงๆ นี่คือตัวอย่างทั้งหมดของสิ่งTextViewที่ถูกแทนที่เพื่อจัดการเหตุการณ์การสัมผัส:

public class CustomTextView extends AppCompatTextView {

    public CustomTextView(Context context) {
        super(context);
    }

    public CustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                return true;

            case MotionEvent.ACTION_UP:
                performClick();
                return true;
        }
        return false;
    }

    // Because we call this from onTouchEvent, this code will be executed for both
    // normal touch events and for when the system calls this using Accessibility
    @Override
    public boolean performClick() {
        super.performClick();
        doSomething();
        return true;
    }

    private void doSomething() {
        Toast.makeText(getContext(), "did something", Toast.LENGTH_SHORT).show();
    }
}

จากนั้นคุณจะใช้มันดังนี้:

<com.example.myapp.CustomTextView
    android:id="@+id/textview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="20dp"
    android:text="Click me to do something"/>

ดูคำตอบอื่น ๆ ของฉันสำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการสร้างมุมมองที่กำหนดเอง

ตัวเลือกที่ 2: ปิดเสียงคำเตือน

ในบางครั้งอาจเป็นการดีกว่าที่จะปิดเสียงเตือน ตัวอย่างเช่นฉันไม่แน่ใจว่าคุณต้องการทำอะไรกับเหตุการณ์Buttonที่คุณต้องการสัมผัส หากคุณต้องสร้างปุ่มที่กำหนดเองและเรียกperformClick()เข้าonTouchEventเหมือนที่ฉันทำด้านบนเพื่อกำหนดเองTextViewมันจะถูกเรียกสองครั้งทุกครั้งเพราะButtonโทรไปแล้วperformClick()สายแล้ว

ต่อไปนี้เป็นเหตุผลสองประการที่คุณอาจต้องการปิดคำเตือน:

  • งานที่คุณกำลังดำเนินการกับเหตุการณ์สัมผัสของคุณเป็นเพียงภาพเท่านั้น ไม่มีผลต่อการทำงานจริงของแอปของคุณ
  • คุณเป็นคนเย็นชาและไม่สนใจที่จะทำให้โลกนี้น่าอยู่ขึ้นสำหรับคนตาบอด
  • คุณขี้เกียจคัดลอกและวางรหัสที่ฉันให้ไว้ในตัวเลือกที่ 1 ด้านบน

เพิ่มบรรทัดต่อไปนี้ที่จุดเริ่มต้นของวิธีการเพื่อระงับคำเตือน:

@SuppressLint("ClickableViewAccessibility")

ตัวอย่างเช่น:

@SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button myButton = findViewById(R.id.my_button);
    myButton.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            return false;
        }
    });
}

1
ฉันใช้ Customviews เนื่องจากใช้แบบอักษรที่แตกต่างกัน เนื่องจากตอนนี้ใน Api 26 แนะนำฟีเจอร์ใหม่ฟอนต์ใน xml และสำหรับเวอร์ชันเก่าให้ใช้ไลบรารีสนับสนุน 26 ซึ่งรองรับจนถึง Api 16 ดังนั้นฉันจึงลบมุมมองที่กำหนดเองทั้งหมดออก และคำเตือนที่โง่เขลานี้เกิดขึ้นและวิธีแก้ปัญหาคือการสร้างมุมมองแบบกำหนดเองที่ฉันใช้ setOnTouchListener อีกครั้ง hahaha: D แปลกมาก
Shan Xeeshi

19
ฉันสงสัยว่า Google รู้หรือไม่ว่าพวกเขาเสียเวลาไปกี่ชั่วโมง ฉันหมายความว่าพวกเขาสามารถจัดการสิ่งนี้ได้ภายใน api? การใช้เวลาในการดูคลาสย่อยหรือแม้กระทั่งค้นหาวิธีแก้ไขคำเตือนของเขาทำให้เสียเวลาไปมาก
TatiOverflow

ถ้าคุณต้องการMotionEvent eventวัตถุในdoSomething()วิธีการของคุณล่ะ? event.getY()ฉันจำเป็นต้องตรวจสอบ
Mateus Gondim

@MateusGondim ผมต้องบอกว่าผมยังไม่ได้มีอำนาจมากในการดำเนินการperformClick()เลย คิดเริ่มต้นของฉันคือถ้าevent.getY()ไม่ได้เป็นส่วนที่สำคัญของเหตุการณ์ที่เกิดขึ้นจริงคลิก (เช่นผลกระทบ UI ภาพ) onTouchEvent()จากนั้นย้ายไปที่ตรรกะกลับไป มิฉะนั้นคุณสามารถสร้างตัวแปรสมาชิกระดับการจัดเก็บการกระทำที่ผ่านมาYค่า ฉันขอแนะนำให้คุณตรวจสอบซอร์สโค้ดสำหรับมุมมองมาตรฐานบางส่วนเพื่อดูว่า Android ใช้งานอย่างไร ฉันต้องศึกษาพวกเขาให้มากขึ้นด้วยตัวเอง
Suragch

1
@sisisisi เตือนขึ้นมาเมื่อคุณแทนที่แต่ไม่onTouchEvent() performClick()ซึ่งอาจรวมถึงการปัดหรือคลิกหรือเหตุการณ์สัมผัสอื่น ๆ ที่คุณพยายามจับภาพ
Suragch

17

สารละลาย:

  1. สร้างคลาสที่ขยายปุ่มหรือมุมมองใด ๆ ที่คุณกำลังใช้และลบล้างperformClick ()

    class TouchableButton extends Button {
    
        @Override
        public boolean performClick() {
            // do what you want
            return true;
        }
    }
  2. ตอนนี้ใช้ TouchableButton นี้ใน xml และ / หรือรหัสแล้วคำเตือนจะหายไป!


18
นี่เป็นขั้นต้นจริงๆ ไม่มีวิธีใดที่จะใช้มุมมองที่มีอยู่?
นม

@ นมนป. android.widget.Buttonฮาร์ดโค้ดจึงไม่อนุญาตให้คุณทำเช่นนี้ และดูเหมือนว่าจะได้รับความตั้งใจอย่างมากจากทีม Android dev
tom_mai78101

11

คุณลองเพิ่ม:

view.performClick()

หรือเพิ่มคำอธิบายประกอบการระงับลินต์:

@SuppressLint("ClickableViewAccessibility")

เหรอ?


2
ใช่. มาพร้อมกับ Android Studio 3.0 edition
kas

1
โอเคฉันมีทางเลือกอื่นในการแก้ไขคำเตือนนั้น โปรดดู: stackoverflow.com/questions/47170075/…
แลมด้า

1

การควบคุมมุมมองแบบกำหนดเองอาจต้องใช้ลักษณะการทำงานของเหตุการณ์การสัมผัสที่ไม่ได้มาตรฐาน ตัวอย่างเช่นการควบคุมแบบกำหนดเองอาจใช้วิธีการฟัง onTouchEvent (MotionEvent) เพื่อตรวจจับเหตุการณ์ ACTION_DOWN และ ACTION_UP และทริกเกอร์เหตุการณ์คลิกพิเศษ เพื่อรักษาความเข้ากันได้กับบริการการเข้าถึงรหัสที่จัดการเหตุการณ์คลิกที่กำหนดเองนี้ต้องทำสิ่งต่อไปนี้:

สร้าง AccessibilityEvent ที่เหมาะสมสำหรับการคลิกที่ตีความ เปิดใช้งานบริการการเข้าถึงเพื่อดำเนินการคลิกที่กำหนดเองสำหรับผู้ใช้ที่ไม่สามารถใช้หน้าจอสัมผัสได้ เพื่อจัดการกับข้อกำหนดเหล่านี้อย่างมีประสิทธิภาพโค้ดของคุณควรแทนที่เมธอด performClick () ซึ่งจะต้องเรียกการใช้งานขั้นสูงของวิธีนี้จากนั้นจึงดำเนินการตามที่เหตุการณ์คลิกต้องการ เมื่อตรวจพบการดำเนินการคลิกที่กำหนดเองโค้ดนั้นควรเรียกใช้เมธอด performClick () ของคุณ

https://developer.android.com/guide/topics/ui/accessibility/custom-views#custom-touch-events

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