Tombol Android telah memanggil setOnTouchListener tetapi tidak menggantikan performClick

113

Saat saya mencoba menambahkan onTouchListner()ke tombol, saya mendapat

Tombol telah memanggil setOnTouchListener tetapi tidak menggantikan performClick

peringatan. Apakah ada yang tahu cara memperbaikinya?

1

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

Kesalahan:

Tampilan kustom telah memanggil setOnTouchListener tetapi tidak menggantikan performClick Jika Tampilan yang mengganti onTouchEvent atau menggunakan OnTouchListener juga tidak mengimplementasikan performClick dan memanggilnya saat klik terdeteksi, Tampilan tersebut mungkin tidak menangani tindakan aksesibilitas dengan benar. Penanganan logika dari tindakan klik idealnya ditempatkan di View # performClick karena beberapa layanan aksesibilitas memanggil performClick saat tindakan klik harus terjadi.

kas
sumber
Tampilan kustom ImageViewtelah memanggil setOnTouchListener tetapi tidak mengganti performClick Jika Tampilan yang mengganti onTouchEvent atau menggunakan OnTouchListener juga tidak mengimplementasikan performClick dan memanggilnya saat klik terdeteksi, Tampilan tersebut mungkin tidak menangani tindakan aksesibilitas dengan benar. Penanganan logika dari tindakan klik idealnya ditempatkan di View # performClick karena beberapa layanan aksesibilitas memanggil performClick saat tindakan klik harus terjadi.
kas
Silakan lihat jawaban saya di sini: stackoverflow.com/questions/47170075/…
lambda

Jawaban:

134

Peringatan ini muncul karena Android ingin mengingatkan Anda untuk memikirkan orang buta atau tunanetra yang mungkin menggunakan aplikasi Anda. Saya sarankan Anda menonton video ini untuk gambaran singkat tentang seperti apa itu.

Tampilan UI standar (seperti Button, TextViewdll.) Semuanya disiapkan untuk memberikan masukan yang sesuai kepada pengguna tuna netra melalui layanan Aksesibilitas. Saat Anda mencoba menangani acara sentuh sendiri, Anda berisiko lupa memberikan umpan balik itu. Untuk inilah peringatan itu.

Opsi 1: Buat tampilan kustom

Menangani peristiwa sentuh biasanya merupakan sesuatu yang dilakukan dalam tampilan kustom. Jangan tutup opsi ini terlalu cepat. Tidak terlalu sulit. Berikut adalah contoh lengkap TextViewyang diganti untuk menangani peristiwa sentuh:

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();
    }
}

Maka Anda hanya akan menggunakannya seperti ini:

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

Lihat jawaban saya yang lain untuk detail lebih lanjut tentang membuat tampilan kustom.

Opsi 2: Membungkam peringatan

Di lain waktu, mungkin lebih baik diam saja peringatan itu. Misalnya, saya tidak yakin apa yang ingin Anda lakukan dengan Buttonacara sentuh yang Anda perlukan. Jika Anda adalah untuk membuat tombol kustom dan disebut performClick()dalam onTouchEventseperti yang kulakukan di atas untuk kustom TextView, maka akan dipanggil dua kali setiap waktu karena Buttonsudah panggilan performClick().

Berikut beberapa alasan Anda mungkin ingin membungkam peringatan:

  • Pekerjaan yang Anda lakukan dengan acara sentuh hanyalah visual. Ini tidak memengaruhi kerja aplikasi Anda yang sebenarnya.
  • Anda berhati dingin dan tidak peduli tentang membuat dunia menjadi tempat yang lebih baik bagi orang buta.
  • Anda terlalu malas untuk menyalin dan menempelkan kode yang saya berikan kepada Anda pada Opsi 1 di atas.

Tambahkan baris berikut ke awal metode untuk menyembunyikan peringatan:

@SuppressLint("ClickableViewAccessibility")

Sebagai contoh:

@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;
        }
    });
}
Suragch
sumber
1
Saya menggunakan tampilan khusus karena menggunakan font yang berbeda. Seperti sekarang di Api 26 memperkenalkan fitur baru, font dalam xml dan untuk versi yang lebih lama menggunakan pustaka dukungan 26 yang mendukung hingga Api 16. Jadi saya menghapus semua tampilan kustom. Dan peringatan bodoh ini muncul dan solusinya adalah membuat kembali beberapa tampilan kustom yang saya gunakan setOnTouchListener. hahaha: D Aneh sekali
Shan Xeeshi
19
Saya ingin tahu apakah google menyadari berapa banyak jam pengembang yang mereka buang dengan ini. Maksudku, mereka mungkin bisa menangani ini di dalam api? menghabiskan waktu untuk subclassing views atau bahkan mencari cara untuk menyelesaikan peringatannya menghabiskan banyak waktu.
TatiOverflow
bagaimana jika Anda membutuhkan MotionEvent eventobjek dalam doSomething()metode Anda ? Saya perlu memeriksa event.getY().
Mateus Gondim
@MateusGondim, saya harus mengatakan bahwa saya masih belum kompeten dalam mengimplementasikan performClick(). Pikiran awal saya adalah jika event.getY()tidak terpisahkan dengan kejadian klik yang sebenarnya (yaitu efek UI visual), kemudian pindahkan logika itu kembali ke onTouchEvent(). Jika tidak, Anda dapat membuat variabel anggota kelas untuk menyimpan nilai tindakan naik terakhir Y. Saya juga menyarankan Anda memeriksa kode sumber untuk beberapa tampilan standar jadi lihat bagaimana Android mengimplementasikannya. Saya sendiri perlu mempelajarinya lebih banyak.
Suragch
1
@sisisisi, peringatan akan muncul saat Anda menimpa onTouchEvent()tetapi tidak performClick(). Itu bisa termasuk gesekan atau klik atau peristiwa sentuh lainnya yang Anda coba tangkap.
Suragch
17

Larutan:

  1. Buat kelas yang memperluas Button atau tampilan apa pun yang Anda gunakan dan timpa performClick ()

    class TouchableButton extends Button {
    
        @Override
        public boolean performClick() {
            // do what you want
            return true;
        }
    }
  2. Sekarang gunakan TouchableButton ini dalam xml dan / atau kode dan peringatan akan hilang!

Sjd
sumber
18
Ini sangat menjijikkan. Apakah tidak ada cara untuk menggunakan tampilan yang ada?
Susu
@SusuTidak. android.widget.Buttondi-hardcode sehingga tidak memungkinkan Anda melakukan ini. Dan sepertinya sangat disengaja dari tim pengembang Android.
tom_mai78101
11

Sudahkah Anda mencoba menambahkan:

view.performClick()

atau menambahkan anotasi suppresslint:

@SuppressLint("ClickableViewAccessibility")

?

lambda
sumber
2
Iya. Waring ini datang dengan edisi android studio 3.0
kas
1
Oke, saya punya alternatif untuk memperbaiki peringatan itu. silakan lihat: stackoverflow.com/questions/47170075/…
lambda
1

Kontrol tampilan khusus mungkin memerlukan perilaku peristiwa sentuh non-standar. Misalnya, kontrol kustom dapat menggunakan metode listener onTouchEvent (MotionEvent) untuk mendeteksi peristiwa ACTION_DOWN dan ACTION_UP serta memicu peristiwa klik khusus. Untuk menjaga kompatibilitas dengan layanan aksesibilitas, kode yang menangani peristiwa klik kustom ini harus melakukan hal berikut:

Buat AccessibilityEvent yang sesuai untuk tindakan klik yang ditafsirkan. Aktifkan layanan aksesibilitas untuk melakukan tindakan klik kustom bagi pengguna yang tidak dapat menggunakan layar sentuh. Untuk menangani persyaratan ini dengan cara yang efisien, kode Anda harus mengganti metode performClick (), yang harus memanggil implementasi super metode ini dan kemudian menjalankan tindakan apa pun yang diperlukan oleh kejadian klik. Ketika tindakan klik khusus terdeteksi, kode itu kemudian harus memanggil metode performClick () Anda.

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

vlazzle.dll
sumber