본문 바로가기
모바일개발(Mobile Dev)/안드로이드개발(Android)

Layout Header View Modify

by 테크한스 2016. 9. 4.
반응형

11
down voteaccepted

Update: With the release of Design Support Library 23.1.1, the following method has been added to address this issue:

/**
 * Gets the header view at the specified position.
 *
 * @param index The position at which to get the view from.
 * @return The header view the specified position or null if the position does not exist in this
 * NavigationView.
 */
public View getHeaderView(int index) {
    ...
}

You can also retrieve the number of headers, in case you have more than one:

/**
 * Gets the number of headers in this NavigationView.
 *
 * @return A positive integer representing the number of headers.
 */
public int getHeaderCount() {
    ...
}

In other words, if you use the headerLayout attribute, you can now get access to the view using above method:

View header = navigationView.getHeaderView(0);
ImageView navProfile = (ImageView) header.findViewById(R.id.navProfilePic);

Original answer below left intact for background and/or educational purposes.


I'm going to make an educated guess and say that the following line is probably inflating a view from your NavigationView's header layout:

final ImageView navProfile = (ImageView) findViewById(R.id.navProfilePic);

Where the header layout is given to the NavigationView using:

app:headerLayout="@layout/nav_drawer_header"

If so, continue reading...

With the 23.1.0 release of the design support library, the internal implementation of NavigationView changed to leverage RecyclerView (rather than ListView). With that change, the header has now become another 'item' in the view, meaning it doesn't become available untilafter the initial layout pass. As such, with your current code, when the findViewById() lookup executes, the RecyclerView hasn't set up the header yet, and hence the result of the lookup ends up being null.

The 'issue' has been reported and the consensus is that getting the header view is going to be exposed with a new method on the NavigationView (most likely just called getHeaderView()). Until this is rolled out, there are two obvious workarounds I'm aware of.

Workaround #1:

Remove app:headerLayout and inflate and add the header view manually. Then use the resulting layout to look up any views in the header.

View header = navigationView.inflateHeaderView(R.layout.nav_drawer_header);
ImageView navProfile = (ImageView) header.findViewById(R.id.navProfilePic);

Workaround #2:

Don't inflate views until after the initial layout pass. This can easily be accomplished by posting a Runnable to the view's parent's internal message queue, so it gets executed after any pending messages.

View parent = (View) mNavigationView.getParent();
parent.post(new Runnable() {
    @Override public void run() {
        ImageView navProfile = (ImageView) mNavigationView.findViewById(R.id.navProfilePic);
    }
});

Personally, I'd go with #1.

Related:

shareimprove this answer
   
You got it exactly right, thanks for this detailed explanation. I would have probably never have found out the cause myself and would have switched back to 23.0.0. Thanks a ton, again. – Amit Tiwari Oct 27 '15 at 10:22

Now with the 23.1.1 release of the design support library, you can use

View header = navigationView.getHeaderView(0)
ImageView navProfile = (ImageView) header.findViewById(R.id.navProfilePic);
shareimprove this answer


반응형