Android Lollipop, visualização personalizada AppCompat ActionBar não ocupa toda a largura da tela


97

Então, acabei de atualizar minha base de código para o Lollipop e estou tendo problemas com a barra de ação. Estou usando AppCompat e ActionBarActivity e aumentando uma visualização personalizada. Parece que a visualização personalizada não ocupa mais toda a largura da tela, deixando uma faixa fina à esquerda

Prédio com 19 Como costumava ser

Prédio com 21 Como está agora

Este é o código que estou usando para configurar a barra de ação. Alguém tem alguma ideia?

final ActionBar actionBar = getSupportActionBar();
if(actionBar != null) {
    actionBar.setDisplayHomeAsUpEnabled(false);
    actionBar.setDisplayShowHomeEnabled(false);
    actionBar.setDisplayShowTitleEnabled(false);
    actionBar.setDisplayShowCustomEnabled(true);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
    actionBar.setCustomView(R.layout.action_bar_content_search_custom_view);
    actionBar.setBackgroundDrawable(null);
    // actionBar.setStackedBackgroundDrawable(null);
    TextView title = (TextView) actionBar.getCustomView().findViewById(R.id.action_bar_title);
    title.setText(R.string.youtube);
    ImageView back = (ImageView) actionBar.getCustomView().findViewById(R.id.action_bar_back);
    back.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            finish();
        }
    });
}

Editar

Tirar a visualização personalizada e alterar o plano de fundo agora ocupa toda a largura. Portanto, a questão é: como podemos fazer um CustomView ocupar toda a largura da ActionBar?


Se você comentar temporariamente as partes da visualização personalizada, isso se comporta melhor? Se não, eu me inclinaria para isso talvez devido ao seu tema.
CommonsWare

Removi a visualização personalizada e defini seu plano de fundo como o drawable de plano de fundo da ActionBar e o plano de fundo ocupa toda a largura agora
Stevie Kideckel

Você pode dar uma olhada em sua atividade na Visualização de hierarquia, com e sem a visualização customizada, e ver se pode determinar quais regras de layout estão mudando como resultado da visualização customizada. É possível que este seja um bug no novo appcompat-v7.
CommonsWare

Parece-me que é o lugar reservado para cima ImageView. Experimente desativá-lo para começar.
Nikola Despotoski

1
Olá, parece que essa é uma boa solução para que a visualização personalizada ocupe toda a largura. Eu estava sentindo que não estava se expandindo, mesmo com as ponderações de layout definidas. veja aqui: stackoverflow.com/a/20794736/581574
ratana

Respostas:


111

Parece que isso é causado pelas alterações mais recentes ActionBarno na appcompat-v7atualização recente . Parece que há mudanças significativas em como você deve lidar com as barras de ação.

Enfrentei o mesmo problema e depois de ler a ActionBardocumentação , e principalmente a seguinte citação, encontrei uma solução.

A partir do Android L (API de nível 21), a barra de ação pode ser representada por qualquer widget da Barra de Ferramentas no layout do aplicativo. O aplicativo pode sinalizar para a Atividade qual Barra de Ferramentas deve ser tratada como a barra de ação da Atividade. As atividades que usam esse recurso devem usar um dos temas .NoActionBar fornecidos, definir o atributo windowActionBar como false ou não solicitar o recurso de janela.

A meu ver, os AppCompattemas foram alterados e por um lado pareciam quebrar algumas coisas, mas fornecer muito mais flexibilidade por outro. Eu recomendo seguir estas etapas:

  1. Use o .NoActionBarestilo em sua atividade conforme descrito na citação acima
  2. Adicione um android.support.v7.widget.Toolbarao seu layout de atividade
  3. Defina o app:contentInsetStart="0dp"atributo. Este é o principal problema com a margem que você descreve em sua pergunta
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/actionBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:contentInsetEnd="0dp"
    app:contentInsetStart="0dp" >
</android.support.v7.widget.Toolbar>

Normalmente é recomendado que você faça isso em um arquivo de layout separado e use includeem seu layout de atividade, então você só precisará personalizar a barra de ferramentas em um lugar se for usada em várias atividades

<include layout="@layout/view_action_bar" />
  1. Use findViewByIde setSupportActionBarem sua atividade onCreateparasignal to the Activity which Toolbar should be treated as the Activity's action bar
Toolbar actionBar = (Toolbar) findViewById(R.id.actionBar);
setSupportActionBar(actionBar);
  1. Depois de fazer isso, todas as ações adicionadas onCreateOptionsMenuserão adicionadas à barra de ferramentas e serão tratadas como a barra de ação da atividade.
  2. Personalize ainda mais a Barra de Ferramentas conforme desejado (Adicionar visualizações secundárias etc.)

1
Estou tentando usar a Barra de Ferramentas com a gaveta de navegação, mas estou recebendo um erroError inflating class fragment
Ahmed Nawaz,

Todo o código relevante é compartilhado na resposta. Parece que você deve iniciar uma nova pergunta para o seu caso, pois parece um problema diferente.
Muzikant

Obrigado. Resolvi o problema substituindo a barra de ação pela Barra de ferramentas.
Ahmed Nawaz,

9
Você não deve usar nomes de pacotes explícitos nas declarações de namespace. Usoxmlns:app="http://schemas.android.com/apk/res-auto"
Liminal

1
Não há necessidade de setCustomView. Basta construir um arquivo de layout com os widgets que você deseja incluir em sua barra de ferramentas (por exemplo, adicionar visualizações filhas ao arquivo de layout descrito na seção 3 da resposta)
Muzikant

51

Em vez de fazer tanto trabalho como mencionado por Muzikant e gostar desta resposta

    getSupportActionBar().setDisplayShowHomeEnabled(false);
    getSupportActionBar().setDisplayShowTitleEnabled(false);
    getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.WHITE));
    LayoutInflater mInflater = LayoutInflater.from(this);

    View mCustomView = mInflater.inflate(R.layout.action_bar_home, null);
    getSupportActionBar().setCustomView(mCustomView);
    getSupportActionBar().setDisplayShowCustomEnabled(true);
    Toolbar parent =(Toolbar) mCustomView.getParent();//first get parent toolbar of current action bar 
    parent.setContentInsetsAbsolute(0,0);// set padding programmatically to 0dp

Você precisa adicionar apenas as duas últimas linhas de código para resolver seu problema.

Espero que isso possa ajudar você e qualquer outra pessoa.

ATUALIZAÇÃO: Depois de fazer algumas pesquisas sobre isso, descobri que esta solução não funcionará em alguns casos. A lacuna do lado esquerdo (HOME ou BACK) será removida com isso, mas a lacuna do lado direito (MENU) permanecerá como está. Abaixo está a solução para esses casos.

View v = getSupportActionBar().getCustomView();
LayoutParams lp = v.getLayoutParams();
lp.width = LayoutParams.MATCH_PARENT;
v.setLayoutParams(lp);

Adicione essas quatro linhas ao código acima, de modo que a lacuna do lado direito também seja removida da barra de ação de suporte.


obrigado! obrigado! as últimas 2 linhas era o que eu estava procurando!
digitalmidges de

Onde adicionamos essas linhas? Depois da parte da Barra de Ferramentas?
Zen de

1
@summers sim, adicione-os imediatamente após o código da barra de ferramentas.
Amrut Bidri

31

Acho que você também pode fazer isso em estilos. tente isso. testei no kitkat

<style name="AppTheme" parent="Theme.AppCompat">
  <item name="toolbarStyle">@style/AppThemeToolbar</item>
</style>

<style name="AppThemeToolbar" parent="Widget.AppCompat.Toolbar" >
  <item name="contentInsetStart">0dp</item>
</style>

1
Esta resposta está errada: android: contentInsetStart requer nível de API 21 (o mínimo atual é 14)
mr.boyfox

Mas, idioma muito bom! Você precisa escrever o estilo separadamente para API 21 e versões anteriores.
mr.boyfox

Esta é a resposta correta para remover a margem esquerda se você ainda estiver usando a barra de ação padrão.
Tooroop

Isso realmente funciona! Com a versão mais recente da biblioteca de suporte, acho que você não precisa declarar os atributos duas vezes (o android: alguns não são necessários).
BoD de

Estive procurando por esse problema e quando encontrei sua resposta, vejo que já votei a favor! Obrigado duas vezes.
user1732313

8

Nenhuma das outras respostas funcionou para mim, então dei uma olhada nos estilos reais do AppCompat v7, encontrados aqui .

Se você olhar o estilo Base.Widget.AppCompat.ActionBar, ele tem:

<item name="contentInsetStart">@dimen/abc_action_bar_content_inset_material</item>
<item name="contentInsetEnd">@dimen/abc_action_bar_content_inset_material</item>

Então, obviamente, só precisamos substituir essas propriedades em nosso próprio estilo de barra de ação:

<style name="ActionBar" parent="@style/Base.Widget.AppCompat.ActionBar">
        <item name="contentInsetStart">0dp</item>
        <item name="contentInsetEnd">0dp</item>
</style>

Isso funcionou muito bem para mim, espero que ajude outras pessoas também.


Sim, como afirma a resposta escolhida, a chave são os atributos contentInsetStart e contentInsetEnd da ActionBar / Toolbar. É válido definir seu próprio estilo, mas você também pode configurá-los para 0dp nos atributos da Barra de Ferramentas em seu xml
Stevie Kideckel

1

Depois de muito bater minha cabeça contra o monitor, isso funcionou para mim

 Toolbar toolbar = (Toolbar) actionBar.getCustomView().getParent();
        toolbar.setContentInsetStartWithNavigation(0);
        toolbar.setContentInsetEndWithActions(0);
        toolbar.setContentInsetsAbsolute(0, 0);
        toolbar.setPadding(0, 0, 0, 0);

GetCustomView (). GetParent () é o que funcionou


0

Eu também encontrei esse problema hoje, então descobri que estava res/values-v21/styles.xmldentro do meu projeto que foi gerado automaticamente pelo Android Studio e essa é a causa.

Por quê?

Porque res/values-v21/styles.xmlo conteúdo do meu era:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="BaseAppTheme" parent="android:Theme.Material.Light">
    </style>
</resources>

E meu res/values/styles.xmlcontinha algo como:

<style name="BaseAppTheme" parent="android:Theme.Holo.Light">
    <!-- Customize your theme here. -->
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:soundEffectsEnabled">false</item>
</style>

Então, quando eu executei meu aplicativo no Lollipop, o res/values-v21/styles.xmlfoi usado, e isso causou exatamente o problema que o OP tinha. Então, cheguei a uma solução simples: apenas excluir:

    <style name="BaseAppTheme" parent="android:Theme.Material.Light">
    </style>

no res/values-v21/styles.xml


0

ao ponto:

 ActionBar actionBar = getSupportActionBar();
                actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
                actionBar.setCustomView(R.layout.actionbar_layout);
                Toolbar toolbar = (Toolbar) actionBar.getCustomView().getParent();
                    toolbar.setContentInsetsAbsolute(0, 0);
                    toolbar.setPadding(0, 0, 0, 0);

certifique-se de importar a barra de ferramentas certa - android.support.v7.widget.Toolbar;


0

Escreva essas duas linhas além do seu código

Toolbar toolbar=(Toolbar)viewActionBar.getParent();
toolbar.setContentInsetsAbsolute(0,0);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.