web-dev-qa-db-ja.com

Androidサポートv23.1.0の更新により、NavigationViewのget / findヘッダーが壊れる

これまでv23.0.1サポートライブラリを問題なく使用してきました。新しいv23.1.0ライブラリに切り替えると、ドロワーレイアウトのウィジェットにnullポインターが表示されます。

mNavigationView = (NavigationView) findViewById(R.id.navigation_view);    
TextView username = (TextView) mNavigationView.findViewById(R.id.username_textView);
//       ^^^^^^^^ is now null when using new library
// which causes the following to fail
username.setText(mUser.getName());

アクティビティレイアウト

<?xml version="1.0" encoding="utf-8"?>
<Android.support.v4.widget.DrawerLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:id="@+id/drawer_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context=".MainActivity">

<LinearLayout
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical">

    <include layout="@layout/toolbar" />

    ...

</LinearLayout>

<Android.support.design.widget.NavigationView
    Android:id="@+id/navigation_view"
    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_items" />

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

drawer_header.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:fresco="http://schemas.Android.com/apk/res-auto"
Android:layout_width="match_parent"
Android:layout_height="150dp"
Android:orientation="vertical">

   <TextView
    Android:id="@+id/username_textView"
    Android:layout_width="match_parent"
    Android:layout_height="0dp" />

    ...

</LinearLayout>

古いバージョンを使用するようにgradleファイルを変更するだけですぐに正常に機能するので、コードにひどい問題はないと思います。私はアップデートで revisions をチェックアウトしましたが、これを引き起こすと思われるものは何も見つかりませんでした。

確かにこれは他の人にも影響を及ぼしますが、手がかりはありますか?

29
Breavyn

設計ライブラリv 23.1.0では、NavigationViewRecyclerViewで機能します。
また、Headerは一種の行になりました。

これは、ヘッダーがビュー階層ですぐに使用できないことを意味します。
navigationView.findViewById(XXX)などのメソッドを使用してヘッダー内のビューを取得すると、問題が発生する可能性があります。

Google Tracker にバグがあります。

EDIT 12/10/2015:デザインライブラリ23.1.1

23.1.1では、 getHeaderView() を使用してNavigationViewのヘッダービューを取得するための新しいAPIが導入されています

23.1.1より前

回避策fot 23.1.0addOnLayoutChangeListenerを使用することができます。次のようなもの:

navigationView.addOnLayoutChangeListener( new View.OnLayoutChangeListener()
{
    @Override
    public void onLayoutChange( ... )
    {
        navigationView.removeOnLayoutChangeListener( this );

        View view = navigationView.findViewById( ... );
    }
} );

別の可能な回避策は次のとおりです:

  • app:headerLayout属性をxmlから削除し、プログラムでヘッダーを追加します。

  • プログラムでheaderViewを拡張します。

このようなものを使用してください:

View headerLayout = navigationView.inflateHeaderView(R.layout.navigation_header);
headerLayout.findViewById(xxx);
41

ヘッダービューをxmlを使用してナビゲーションドロワーにアタッチすることは現在壊れています。解決策は、ビューを手動でインフレートしてアタッチすることです。

アクティビティレイアウト

<Android.support.design.widget.NavigationView
    Android:id="@+id/navigation_view"
    Android:layout_width="wrap_content"
    Android:layout_height="match_parent"
    Android:layout_gravity="start"
    Android:fitsSystemWindows="true"
    app:headerLayout="@layout/drawer_header" <!-- remove this line -->
    app:menu="@menu/drawer_items" />

次に、コードで次のようにしてインフレートし、ヘッダーを添付します。

NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_view);
View drawerHeader = navigationView.inflateHeaderView(R.layout.drawer_header);

TextView username = (TextView) drawerHeader.findViewById(R.id.username_textView);
11
Breavyn

新しいNavigationViewでは、ヘッダーはRecyclerViewの行タイプになりました。これにより、あなたまたは誰もが必要なviewによってidを見つけることができます。それを回避し、addOnLayoutChangeListenerリスナーを使用すると、viewを見つけることができます。どこかに文書化する必要があることを知っていますが、Android meh!のようにしてください。

0
k0sh

Android sdk managerからビルドツールを更新したので、23.1.0も正常に動作しています。

使ってます

buildToolsVersion "23.0.2"

これ以前は23.0.1でした。

使用する必要はありません

(View)navigationView.findViewById(R.id.idOfViewFromHeaderView);

あなたの活動では直接使用できます

(View)findViewById(R.id.idOfViewFromHeaderView);
0
Muhammad Adil
0
xushao