NavigationView obter / encontrar o layout do cabeçalho

171

No meu NavigationView, tenho um layout de cabeçalho com o id 'viewId' com botões ativos. Para configurar esses botões, faça o seguinte nas atividades onPostCreate:

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

Com a nova versão da biblioteca de suporte Android, ( 23.1.0 ), a visualização não pode ser encontrada, ela retorna nula. Nas versões anteriores, funcionava bem. É um bug ou estou usando esse recurso errado? Se sim, como acessar o layout do cabeçalho e adicionar comportamento a ele?

khusrav
fonte

Respostas:

429

A versão 23.1.0 passa NavigationViewa usar a RecyclerView(e não a anterior ListView) e o cabeçalho é adicionado como um desses elementos. Isso significa que não está disponível instantaneamente para ligar findViewById()- é necessário um passe de layout antes de ser anexado ao NavigationView.

Para a versão 23.1.1 da Biblioteca de suporte, agora você pode obter uma referência à visualização do cabeçalho usando getHeaderView():

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

Isso tem a vantagem de trabalhar em cabeçalhos adicionados via XML e via código.

Se você ainda estiver usando o 23.1.0, conforme o bug relacionado , poderá aumentar o cabeçalho no código e usar findViewById()isso:

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

Até você passar para 23.1.1.

ianhanniballake
fonte
1
Obrigado pela ajuda imediata, usará a solução alternativa. Tendo o método dedicado parece o caminho a percorrer, a esperança o terá em versões futuras.
khusrav
2
@AlexanderFarber - o código eu postei obras apoiar a API 7
ianhanniballake
4
Eu prefiro fazer o downgrade de bibliotecas. A introdução de um bug é como uma assinatura do Google. Se a nova versão tiver um bug, o Google lançou essa nova versão
BamsBamx 19/10/2015
1
@GFPF - quando você liga inflateHeaderView, ele anexa o modo de exibição para você na camada correta no RecyclerViewcom o pai correto - algo que você não pode fazer externamente NavigationView.
Ianhanniballake #
1
@RmK - obrigado, atualizei para responder para refletir as novas APIs adicionadas na 23.1.1 para recuperar cabeçalhos adicionados via XML (como a solução alternativa anterior funcionava apenas nos cabeçalhos adicionados via código).
ianhanniballake
142

Agora, com a versão 23.1.1 da biblioteca de suporte ao design, você pode usar

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
fonte
Você também pode usar navigationView.getHeaderCount()se tiver mais de um cabeçalho por qualquer motivo.
Francois Dermu 13/11/2015
13

É assim que eu fiz isso usando ButterKnifee funciona para mim.

protected static class HeaderViewHolder {

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

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

e, em seguida, use esse suporte de exibição como este:

View header = navigationView.getHeaderView(0);
headerViewHolder = new HeaderViewHolder(header);
Wahib Ul Haq
fonte
2
Isso é perfeito quando você deseja remover a lógica relacionada à vista da sua atividade. Boa ideia!
amouly
2
Está funcionando perfeitamente com o ButterKnife, obrigado irmão.
Rajesh Naddy
8

Para mim, foi a mesma situação com 23.1.0, após a atualização, a exceção de ponteiro nulo se tornou. Nesse caso, é NavigatorViewparecido com:

<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"/>

Eu tentei a proposta de solução por ianhanniballake, mas ela não funciona. Então eu inflado com a frase:

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

Depois disso, posso encontrar por ID todas as visualizações definidas no nav_heardlayout.

Campino
fonte
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
fonte
Olá e bem-vindo ao Stack Overflow! Adicione um texto explicando como isso resolve a pergunta acima. Obrigado!
19619 Jonathan
0

No código Kotlin @Francois Dermu seja

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

Versão 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
fonte