获取NavigationView的Header中View的方法

  在使用 ButterKnife 8.4.0 和 Support Library 24.2.1 的时候,使用 ButterKnife 绑定 NavigationView 的 Header 里面的 View 时抛出 IllegalStateException 异常,指示“Required view ‘header_text’ with ID 2131492989 for field ‘mTextView’ was not found”。所使用的 NavigationView 使用 headerLayout 配置了 Header 的布局:

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

nav_header.xml 在 LinearLayout 中放置了若干 Widget:

<LinearLayout 
    ...>
    ...
    <TextView
        android:id="@+id/header_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

  使用 ButterKnife 绑定 nav_header.xml 中的 header_text 时,抛出了如前所述的异常。如果直接用 findViewById(),如:

TextView textView = (TextView) findViewById(R.id.header_text);

这里的 textView 会是 null,依旧无法找到 header_text。经尝试发现,如果 findViewById() 的时间较晚,比如在按了某个按钮之后,findViewById() 就可以找到 header_text。

  根据相关 Issue,似乎并不希望使用 findViewById() 暴露 NavigationView 的 Header。Support Library 23.1.1 为 NavigationView 加入了 getHeaderView() 方法,可以用于获取 NavigationView 的 Header,之后就可以由 Header 获取其中的View:

View header = navigationView.getHeaderView(0);
TextView textView = (TextView) header.findViewById(R.id.header_text);

这样就可以成功获取到 header_text 了。

  另外一种方法是,不在布局文件中使用 headerLayout 属性为 NavigationView 指明 Header,而是通过 inflateHeaderView() 手动添加,然后再在 inflateHeaderView() 所返回的 View(也就是 NavigationView 的 Header)上使用 findViewById():

NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
View header = navigationView.inflateHeaderView(R.layout.nav_header);
TextView textView = (TextView) header.findViewById(R.id.header_text);