NavigationView dapatkan / temukan tata letak tajuk

171

Di NavigationView saya, saya memiliki tata letak tajuk dengan id 'viewId' dengan tombol aktif. Untuk mengatur tombol-tombol itu, saya melakukan hal berikut dalam aktivitas onPostCreate:

final View panel = findViewById(R.id.viewId);
panel.setOnClickListener(new View.OnClickListener() {
... setup goes here ...
});

Dengan pustaka dukungan android versi baru, ( 23.1.0 ), tampilan tidak dapat ditemukan, menghasilkan null. Dengan versi sebelumnya itu bekerja dengan baik. Apakah ini bug atau apakah saya menggunakan fitur ini salah? Jika demikian, bagaimana cara mengakses tata letak tajuk dan menambahkan perilaku ke dalamnya?

khusrav
sumber

Jawaban:

429

Versi 23.1.0 beralih NavigationViewke menggunakan RecyclerView(bukan yang sebelumnya ListView) dan header ditambahkan sebagai salah satu elemen tersebut. Ini berarti itu tidak tersedia secara instan untuk memanggil findViewById()- pass tata letak diperlukan sebelum terpasang ke Internet NavigationView.

Untuk versi 23.1.1 dari Perpustakaan Dukungan, Anda sekarang bisa mendapatkan referensi ke tampilan header menggunakan getHeaderView():

View headerLayout = navigationView.getHeaderView(0); // 0-index header

Ini memiliki keuntungan bekerja pada header yang ditambahkan melalui XML dan melalui kode.

Jika Anda masih menggunakan 23.1.0, sesuai bug terkait , Anda dapat mengembang header dalam kode dan menggunakannya findViewById():

View headerLayout = 
    navigationView.inflateHeaderView(R.layout.navigation_header);
panel = headerLayout.findViewById(R.id.viewId);
// panel won't be null

Sampai Anda pindah ke 23.1.1.

ianhanniballake
sumber
1
Terima kasih atas bantuan yang cepat, akan menggunakan solusinya. Memiliki metode khusus sepertinya cara untuk pergi, harapan akan memilikinya dalam rilis mendatang.
khusrav
2
@AlexanderFarber - kode yang saya posting berfungsi kembali ke API 7
ianhanniballake
4
Saya lebih suka downgrade libs. Memperkenalkan bug seperti tanda tangan dari Google. Jika versi baru memiliki bug, maka Google merilis versi baru
BamsBamx
1
@ GFPF - ketika Anda menelepon inflateHeaderView, itu melampirkan tampilan untuk Anda di lapisan yang benar RecyclerViewdengan orang tua yang benar - sesuatu yang tidak dapat Anda lakukan secara eksternal NavigationView.
ianhanniballake
1
@RmK - terima kasih, saya telah memperbarui untuk menjawab untuk mencerminkan API baru yang ditambahkan di 23.1.1 untuk mengambil header yang ditambahkan melalui XML (karena solusi sebelumnya hanya bekerja pada header yang ditambahkan melalui kode).
ianhanniballake
142

Sekarang dengan rilis 23.1.1 perpustakaan dukungan desain, Anda dapat menggunakan

NavigationView navigationView = (NavigationView) findViewById(R.id.your_nav_view_id);
View header = navigationView.getHeaderView(0)
TextView text = (TextView) header.findViewById(R.id.textView);
Francois Dermu
sumber
Anda juga dapat menggunakan navigationView.getHeaderCount()jika Anda memiliki lebih dari 1 tajuk untuk alasan apa pun.
Francois Dermu
13

Ini adalah bagaimana saya menggunakannya ButterKnifedan berfungsi untuk saya.

protected static class HeaderViewHolder {

    @BindView(R.id.button)
    Button button;

    HeaderViewHolder(View view) {
        ButterKnife.bind(this, view);
    }
}

dan kemudian gunakan pemegang tampilan ini seperti ini:

View header = navigationView.getHeaderView(0);
headerViewHolder = new HeaderViewHolder(header);
Wahib Ul Haq
sumber
2
Ini sempurna ketika Anda ingin menghapus Lihat logika terkait dari Aktivitas Anda. Ide yang hebat!
amouly
2
Ini bekerja sempurna dengan ButterKnife, terima kasih saudara.
Rajesh Naddy
8

Bagi saya itu adalah situasi yang sama dengan 23.1.0, setelah memperbarui pengecualian null pointer menjadi. Dalam hal ini NavigatorViewterlihat seperti:

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

Saya mencoba proposal solusi oleh ianhanniballake tetapi tidak berhasil. Lalu saya menggelembungkan kalimat itu:

LayoutInflater.from(getContext()).inflate(R.layout.nav_header, mNavigationView);

Setelah itu, saya dapat menemukan id semua tampilan yang didefinisikan dalam nav_heardtata letak.

Campino
sumber
3
NavigationView navigationView = findViewById(R.id.your_nav_view);
View header = navigationView.getHeaderView(0);
TextView textUsername = header.findViewById(R.id.textView);
textUsername.setText("you text here ");
indrit saveta
sumber
Halo dan selamat datang di Stack Overflow! Harap tambahkan beberapa teks yang menjelaskan bagaimana ini menyelesaikan pertanyaan yang diajukan di atas. Terima kasih!
Jonathan
0

Dalam kode Kotlin @ Francois Dermu menjadi seperti

val navigationView : NavigationView = findViewById(R.id.your_nav_view_id);
val header = navigationView.getHeaderView(0)
val textView = header.findViewById<TextView>(R.id.textView)
Alex
sumber
0

Versi Kotlin.

val navView: NavigationView = findViewById(R.id.nav_view)       
// set User Name
val headerView: View = navView.getHeaderView(0)
headerView.txtUserName.text = "User Name Goes here"
Qadir Hussain
sumber