NavigationView onClick dari xml menyebabkan kesalahan

Menggunakan NavigationView dari pustaka desain dukungan Android yang baru dirilis, jika tata letak header navigasi menyertakan onClick (dalam xml), peristiwa onClick membuat aplikasi mogok. OnClick dapat ditambahkan secara terprogram melalui view.onClickListener (bukan xml), dan kemudian mengklik berfungsi dengan baik. Namun karena alasan tertentu, setiap kali xml onClick digunakan, selalu terjadi kesalahan.

Inilah tata letak utama saya:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/mainActivityLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <RelativeLayout
        android:id="@+id/mainContentFrame"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        ...

    </RelativeLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/drawerNavView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/drawer_header"
        app:menu="@menu/drawer_menu">

    </android.support.design.widget.NavigationView>

</android.support.v4.widget.DrawerLayout>

Dalam aktivitas saya, klik item menu saya (ditambahkan dengan navView.setNavigationItemSelectedListener()) berfungsi dengan baik. Masalahnya adalah ketika header diklik:

laci_header.xml:

...

<View
    android:id="@+id/testButton"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:onClick="testButtonClick"/>

...

Menghasilkan kesalahan berikut:

java.lang.IllegalStateException: Could not find a method testButtonClick(View) 
in the activity class android.view.ContextThemeWrapper for onClick handler
on view class android.view.View with id 'testButton'

PEMBARUAN

NavigationView dapat menggunakan file sumber daya Menu standar, namun ada masalah serupa jika menggunakan onClick dari sumber daya menu XML. Menurut referensi Sumber Daya Menu, atribut android:onClick menggantikan atribut normal panggilan balik. Ini biasanya berfungsi dengan baik, tetapi dengan item menu di NavigationView, tidak. Sebaliknya, ia crash dengan kesalahan ini:

java.lang.RuntimeException: Unable to start activity ComponentInfo{...}:
android.view.InflateException: Binary XML file line #34: 
Error inflating class android.support.design.widget.NavigationView

Kesalahan hilang ketika saya menghapus XML onClick.

PEMBARUAN

Saya menguji xml onClick menggunakan proyek demo "resmi" untuk Perpustakaan Desain Android. Hasil yang sama: menambahkan onClick (dalam xml) ke menu atau header NavigationView menyebabkan aplikasi mogok. Jadi sepertinya ini adalah bug pada NavigationView.

DISELESAIKAN DI v23.1

Google merilis perbaikan untuk error XML onClick ini di Support Library v23 .1.


person hungryghost    schedule 31.05.2015    source sumber
comment
apakah Anda menggunakan fragmen   -  person Elltz    schedule 31.05.2015
comment
Ya, saya menggunakan fragmen dan viewpager.   -  person hungryghost    schedule 31.05.2015
comment
nah jadi onclick di xml tidak akan berfungsi dalam aktivitas karena karena tampilan header berada di kelas fragmen, masuk akal pak?   -  person Elltz    schedule 31.05.2015
comment
Saya tidak mengerti apa yang Anda katakan. Saya menggunakan viewpager dan fragmen, tetapi hanya di area konten utama saya, bukan di laci saya. Tampilan header saya ditambahkan melalui XML ke widget NavigationView baru. Header itu hanyalah file tata letak XML lainnya. Apakah saya melewatkan sesuatu?   -  person hungryghost    schedule 31.05.2015
comment
Mungkin ini akan membuat @Elltz kata-kata lebih jelas.   -  person Simas    schedule 31.05.2015
comment
@Simas, terima kasih atas tautannya, tetapi onClick ini bukan dari Fragmen. Ini dari NavigationView dalam suatu Aktivitas.   -  person hungryghost    schedule 31.05.2015
comment
Anda harus menggunakan OnNavigationItemSelectedListener. Karena benar, bersih, sederhana dan memungkinkan perluasan dan modifikasi kode dengan mudah. Mengenai masalah ini, Anda harus memposting seluruh stacktrace. Kita dapat melihat kode sumber untuk mendapatkan beberapa petunjuk atau kemungkinan besar menyelesaikannya.   -  person    schedule 19.06.2015


Jawaban (4)


Dikonfirmasi, ini adalah bug di perpustakaan dukungan.

Rupanya ini terkait dengan ContextThemeWrapper, dan menurut laporan bug ini , masalahnya ada di Support Library 22.1.

Jadi, jawaban singkatnya adalah:

Jangan gunakan XML onClick dengan NavigationView (atau beberapa komponen lain seperti EditText), sampai masalah tersebut diperbaiki.

Solusi:

Tetapkan pemroses klik dalam kode. Untuk NavigationView, gunakan setNavigationItemSelectedListener().

PEMBARUAN: Bug ini telah diperbaiki

Anda kini dapat menggunakan XML onClick di Support Library 23.1 (laporan bug). Saya telah memverifikasi bahwa ini berfungsi di aplikasi saya. Namun tampaknya ada masalah XML (yang lebih baru) lainnya dengan NavView di v23.1 (lihat di bawah), meskipun kesalahan onClick khusus ini telah diperbaiki.

Untuk kelengkapan:

Tampaknya ada bug lain (terkait?) saat menggembungkan header NavigationView melalui XML. Menggunakan XML app:headerLayout menghasilkan kesalahan dengan 23.1, meskipun XML onClick sekarang berfungsi. Karena masalah inflasi ini, Anda harus menggunakan metode NavigationView.inflateHeaderView() dalam kode. Metode baru ini ditambahkan di 23.1 dan, tampaknya, perluasan XML sebelumnya sekarang rusak (atau mungkin mereka tidak lagi menggunakan app:headerLayout tanpa memberi tahu siapa pun?). Info selengkapnya dirinci di sini.

person hungryghost    schedule 05.06.2015
comment
Saya telah menerapkan kasus sakelar pada setNavigationItemSelected..(). untuk membuka berbagai fragmen. Ini berfungsi dengan baik untuk tata letak Telepon tetapi pada tata letak dua panel, kode yang sama tidak berfungsi. kasus Default dipicu. artinya id untuk MenuItem telah berubah. - person Y2K; 14.09.2015

Hai: solusi saya adalah menghapus

app:headerLayout="@layout/drawer_header"

dari tata letak NavigationView Anda seperti di bawah ini:

<android.support.design.widget.NavigationView
    android:id="@+id/drawerNavView"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:menu="@menu/drawer_menu">
</android.support.design.widget.NavigationView>

Dan kemudian gunakan di bawah ini dalam aktivitas atau pengontrol tampilan Anda

NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
View headerView= navigationView.inflateHeaderView(R.layout.nav_header);

TextView tvName = (TextView) headerView.findViewById(R.id.id_nav_header_uname);
tvName.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        L.d("=======tv click=====");
    }
});

ini berhasil untuk saya.

person Summer    schedule 22.10.2015
comment
Maaf. Seperti yang saya katakan di postingan asli saya, kita jelas bisa menambahkan onClick di Java. Bugnya adalah onClick tidak berfungsi dari XML. Bagaimanapun, poin ini masih diperdebatkan sekarang karena Google telah merilis perbaikan bug. Lihat posting saya yang diperbarui untuk info. - person hungryghost; 23.10.2015
comment
Saya melihat bug yang diperbaiki Google, saya menggunakan Support Library 23.1, namun tidak dapat menambahkan onClick kecuali Anda menggunakan navigationView.inflateHeaderView(R.layout.nav_header); untuk memuat tampilan. melalui xml tidak dapat mengatur onClick di NavigationView untuk headerView. - person Summer; 23.10.2015
comment
Tampaknya ada bug lain dengan menggembungkan header NavigationView melalui XML. Saya memiliki masalah yang sama dengan v23.1, tetapi XML onClick berfungsi dengan baik sekarang (saya telah memverifikasi di aplikasi saya). Hanya saja sekarang XML app:headerLayout rusak sehingga terpaksa menggunakan inflateHeaderView() dalam kodenya. Metode ini baru saja ditambahkan di 23.1, jadi sepertinya ada yang rusak dalam implementasinya. Satu langkah maju, satu langkah mundur. Saya mencari info tentang masalah XML app:headerLayout ini minggu lalu, tetapi tidak menemukan apa pun. Mungkin Anda ingin memposting pertanyaan baru untuk itu? - person hungryghost; 23.10.2015
comment
Oh, sepertinya orang lain sudah memposting tentang masalah inflasi ini sejak terakhir kali saya melihatnya. stackoverflow.com/a/33163288/3449044 - person hungryghost; 23.10.2015

Anda dapat menulis metode Anda dalam kode tanpa menyebutkannya dalam XML. Dalam kode Anda cukup menggunakan kode tersebut

public void methodName()
{
//
}

View v = findViewById(R.id.view_id);
v.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
methodName();
}
});
person Vendetta8247    schedule 31.05.2015
comment
Saya tahu saya bisa menambahkan onClickListener, dan itulah yang sudah saya lakukan untuk mengatasi masalah ini. Saya bertanya-tanya mengapa XML onClick tidak berfungsi. Saya pikir ini mungkin bug pada perpustakaan dukungan baru. - person hungryghost; 31.05.2015
comment
@hungryghost sejujurnya saya belum pernah mendalaminya selama cara pengkodeannya terlihat lebih bagus bagi saya dan berhasil. Tapi saya akan terus mengawasi postingan ini kalau-kalau saya menemukan sesuatu yang menarik - person Vendetta8247; 31.05.2015
comment
Pengkodeannya berfungsi dengan baik dan cukup mudah. Namun dalam implementasi khusus saya, saya sebenarnya akan melakukan pertukaran tata letak yang lebih kompleks dan semacamnya, dan XML onClick akan membuatnya sedikit lebih mudah. Tapi bukan itu intinya. Bagi saya, saya hanya terkejut dengan kesalahan ini. Saya tidak tahu mengapa itu tidak berhasil. Selain itu, saya mungkin harus mengubah pertanyaan saya agar lebih jelas apa yang saya tanyakan. Saya merasa saya akan mendapatkan lebih banyak, cukup gunakan jawaban OnClickLIstener kecuali saya lebih eksplisit! - person hungryghost; 31.05.2015
comment
@hungryghost, maaf saya telah menjawabnya. Itu seharusnya menjadi komentar. Saya hanya tidak memiliki 50 reputasi dan kalau-kalau itu bisa membantu saya harus menjawab - person Vendetta8247; 31.05.2015
comment
Oh tidak masalah. Tidak apa-apa Anda menjadikannya jawaban. Saya akan menandainya sebagai benar, tetapi sebenarnya bukan itu yang saya tanyakan. Saya mengedit pertanyaan awal saya untuk memperjelas apa yang saya bicarakan. Semoga berhasil mendapatkan 50 rep itu. Saya akan memberi suara positif pada komentar Anda untuk membantu. Hampir sampai! - person hungryghost; 31.05.2015

NavigationView memiliki OnNavigationItemSelectedListener untuk Item Menu.

e.g.

navigationView.setNavigationItemSelectedListener(new SelectedNavigationItemListener());

private class SelectedNavigationItemListener implements NavigationView.OnNavigationItemSelectedListener {

    @Override
    public boolean onNavigationItemSelected(MenuItem menuItem) {

        switch (menuItem.getItemId()){
            case id1:
                break;
        }

        Log.d("MENU ITEM", menuItem.getTitle().toString());
        return false;
    }

}

Untuk Header Anda dapat melakukan sesuatu seperti ini mis

navigationView = (NavigationView) findViewById(R.id.navigation_view);
View header = navigationView.inflateHeaderView(R.layout.drawer_header);
RelativeLayout drawerHeader = (RelativeLayout) header.findViewById(R.id.drawerHeader);
drawerHeader.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("CLICKED HEADER", "Header Clicked");
    }
});

Referensi untuk HeaderLayout saya:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawerHeader"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="12dp">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/app_name"
    android:textSize="16sp" />

person Hiroga Katageri    schedule 04.06.2015
comment
Maaf, menurut saya Anda salah memahami pertanyaannya. Saya tidak bertanya bagaimana cara menambahkan pendengar klik dalam kode. Pertanyaan saya mengapa ada kesalahan dengan xml onClick. Saya cukup yakin itu adalah bug di perpustakaan. - person hungryghost; 04.06.2015