Como desativar o modo de mudança BottomNavigationView?

146

BottomNavigationView não mostra o título do menu que está inativo.

Como mostrar títulos de todos os elementos do menu em bottomNavigationBar? O problema é que, no meu caso, apenas o título do elemento é clicado.

insira a descrição da imagem aqui

Natan Rubinstein
fonte
1
Possível duplicata da nova barra de navegação inferior
Radhey 21/10
Aqui está uma resposta útil se você quiser completamente remover qualquer animação: stackoverflow.com/a/51052247/2352699
Fred Porciúncula

Respostas:

330

A implementação de BottomNavigationViewtem condição: quando houver mais de 3 itens, use o modo shift.

Neste momento, você não pode alterá-lo através da API existente e a única maneira de desativar o modo de mudança é usar a reflexão.

Você precisará da classe auxiliar:

import android.support.design.internal.BottomNavigationItemView;
import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.widget.BottomNavigationView;
import android.util.Log;
import java.lang.reflect.Field;

public class BottomNavigationViewHelper {
    public static void disableShiftMode(BottomNavigationView view) {
        BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
        try {
            Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
            shiftingMode.setAccessible(true);
            shiftingMode.setBoolean(menuView, false);
            shiftingMode.setAccessible(false);
            for (int i = 0; i < menuView.getChildCount(); i++) {
                BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
                //noinspection RestrictedApi
                item.setShiftingMode(false);
                // set once again checked value, so view will be updated
                //noinspection RestrictedApi
                item.setChecked(item.getItemData().isChecked());
            }
        } catch (NoSuchFieldException e) {
            Log.e("BNVHelper", "Unable to get shift mode field", e);
        } catch (IllegalAccessException e) {
            Log.e("BNVHelper", "Unable to change value of shift mode", e);
        }
    }
}

E, em seguida, aplique o disableShiftModemétodo no seu BottomNavigationView, mas lembre-se, se você estiver inflando a exibição do menu a partir do seu código, será necessário executá-lo após o inflamento.

Exemplo de uso:

BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation_bar);
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

PS.

Lembre-se, você precisará executar esse método sempre que alterar os itens de menu no seu BottomNavigationView.

ATUALIZAR

Você também precisa atualizar o arquivo de configuração do programa (por exemplo, proguard-rules.pro), o código acima usa reflexão e não funcionará se o programa ofuscar o mShiftingModecampo.

-keepclassmembers class android.support.design.internal.BottomNavigationMenuView { 
    boolean mShiftingMode; 
}

Obrigado Muhammad Alfaifi por apontar esse problema e fornecer snippet .

ATUALIZAÇÃO 2

Como Jolanda Verhoef apontou, a nova biblioteca de Suporte ( 28.0.0-alpha1) e também a nova biblioteca de Componentes de Materiais ( 1.0.0-beta01) oferecem uma propriedade pública que pode ser usada para manipular o modo de deslocamento em três itens de menu.

<com.google.android.material.bottomnavigation.BottomNavigationView
    ...
    app:labelVisibilityMode="labeled"
    ... 
/>

Na biblioteca de componentes de material também se aplica se houver 5 itens de menu.

ATUALIZAÇÃO 3

Como o @ThomasSunderland também apontou, você pode definir essa propriedade como false app:itemHorizontalTranslation="false"sem Enabledpostfix para desativar a animação deslocada.

você pode conferir o guia completo sobre como estilizar o BottomNavigation aqui

Przemysław Piechota. kibao
fonte
10
**** Proguard :(
Muhammad Alfaifi
17
O campo será ofuscado por isso não há maneira de mudar o seu valor a menos que você excluí-lo em seu arquivo ProGuard-regras
Muhammad Alfaifi
8
-keepclassmembers class android.support.design.internal.BottomNavigationMenuView {booleano mShiftingMode; }
Muhammad Alfaifi
8
Às vezes, eu realmente me pergunto por que o Google obriga a ver implementações em desenvolvedores. Embora existam quatro opções no próprio aplicativo do Google+, esse recurso simples deveria estar acessível por meio de uma função simples, se disponível! Problema semelhante ocorreu com o TabLayout, que foi corrigido muito mais tarde na biblioteca de suporte. Agradecemos a solução alternativa ao Original Replier e ao @MuhammadAlfaifi por melhorar isso.
sud007
19
A nova biblioteca de suporte (28.0.0-alfa 1) suporta mudar este comportamento através app: labelVisibilityMode = "rotulado"
Jolanda Verhoef
50

Desde a biblioteca de suporte 28.0.0-alpha1:

<android.support.design.widget.BottomNavigationView
    app:labelVisibilityMode="labeled" />
Junbin Deng
fonte
1
Estou usando esta versão da biblioteca de suporte, mas ainda estou recebendo o erro "labelVisibilityMode" não encontrado.
Sagar Maiyad
1
Trabalhando corretamente. Não há necessidade de ir para a reflexão. Graças a tonelada
Bhupesh
1
@Riser certificar-se de que você está usando app:nãoandroid:
Carson Holzheimer
28

Para desativar a animação de texto, você também pode usá-lo no seu arquivo dimens.xml:

<dimen name="design_bottom_navigation_active_text_size">12sp</dimen>

Você também pode precisar adicionar isso no seu manifesto:

tools:override="true"
Pafoid
fonte
não está funcionando. Acredito que tive que adicionar isso em /values/dimens.xml?
Rohan Kandwal
10
@RohanKandwal precisa adicionartools:override="true"
Boy
@ Boy Obrigado, vai tentar.
Rohan Kandwal 27/03
altere apenas o tamanho do texto.
The Dude
Eu só preciso colocar assim no meu arquivo dimens.xml:<dimen name="design_bottom_navigation_active_text_size" tools:ignore="PrivateResource">12sp</dimen>
Fernando Barbosa
22

Agora você pode usar app:labelVisibilityMode="[labeled, unlabeled, selected, auto]"em28-alpha

  • labeled manterá todos os marcadores visíveis.
  • unlabeled mostrará apenas ícones.
  • selected mostrará apenas o rótulo para o item selecionado e os itens de turno.
  • autoescolherá rotulado ou selecionado com base no número de itens que você possui. rotulado para 1 a 3 itens e selecionado para mais de 3 itens.
Aidan Laing
fonte
1
obrigado Lunkie! Este é o melhor e mais fácil solução para mim
Gregriggins36
Onde adicionar esta linha de código. Tentei adicionar, mas não foi encontrado um erro.
Abdulwahid
@Abdulwahid você pode adicionar isso no xml da barra de navegação inferior uma vez que você tem biblioteca de suporte 28 ou superior
Aidan Laing
@Lunkie graças agora é claro, uma vez biblioteca de suporte 28
Abdulwahid
17

Resposta de Przemysław em Kotlin como uma função de extensão

@SuppressLint("RestrictedApi")
fun BottomNavigationView.disableShiftMode() {
    val menuView = getChildAt(0) as BottomNavigationMenuView
    try {
        val shiftingMode = menuView::class.java.getDeclaredField("mShiftingMode")
        shiftingMode.isAccessible = true
        shiftingMode.setBoolean(menuView, false)
        shiftingMode.isAccessible = false
        for (i in 0 until menuView.childCount) {
            val item = menuView.getChildAt(i) as BottomNavigationItemView
            item.setShiftingMode(false)
            // set once again checked value, so view will be updated
            item.setChecked(item.itemData.isChecked)
        }
    } catch (e: NoSuchFieldException) {
        Log.e(TAG, "Unable to get shift mode field", e)
    } catch (e: IllegalStateException) {
        Log.e(TAG, "Unable to change value of shift mode", e)
    }
}

Uso (com extensões Kotlin para Android):

bottom_navigation_view.disableShiftMode()
ElegyD
fonte
Trabalhando para o kotlin. por que precisamos usar esta anotação @SuppressLint ("RestrictedApi"), você pode explicar os pls?
Ranjith Kumar
11

Funciona para mim

bottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

ou

<android.support.design.widget.BottomNavigationView
    app:labelVisibilityMode="labeled" />
UgAr0FF
fonte
o meu estava funcionando bem até o alvo = 27, mas do alvo = 28, está quebrado, o texto não é mais exibido. Mas setLabelVisibilityMode faz o truque para mim, agora funciona como um encanto
joke4me
10

Para desativar a animação de texto e diminuir o tamanho da fonte, use isso no arquivo dimens.xml:

<dimen name="design_bottom_navigation_text_size">10sp</dimen> 
<dimen name="design_bottom_navigation_active_text_size">10sp</dimen>
Abhishek
fonte
Pode-se Navigate-> File...> design_bottom_navigation_item.xmlpara ver que não há nenhuma outra maneira.
arekolek
6

ATUALIZAR

no Android sdk versão 28 e superior, eles foram alterados item.setShiftingMode(false)paraitem.setShifting(false)

Eles também removeram o campo mShiftingMode

Então o uso será

 BottomNavigationHelper.removeShiftMode(bottomNav);
 bottomNav.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);


 private static final class BottomNavigationHelper {
    @SuppressLint("RestrictedApi")
    static void removeShiftMode(BottomNavigationView view) {
        BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
        for (int i = 0; i < menuView.getChildCount(); i++) {
            BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
            //noinspection RestrictedApi
            item.setShifting(false);
            item.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

            // set once again checked value, so view will be updated
            //noinspection RestrictedApi
            item.setChecked(item.getItemData().isChecked());
        }
    }
}
Narek Hayrapetyan
fonte
você pode usar este código abaixo. @SuppressLint ( "RestrictedApi") fun removeShiftMode (vista: BottomNavigationView) {val menuView = view.getChildAt (0) como BottomNavigationMenuView menuView.labelVisibilityMode = LabelVisibilityMode.LABEL_VISIBILITY_LABELED menuView.buildMenuView ()}
Profundo P
5

Como outros já apontaram, desde a biblioteca de suporte 28.0.0-alpha1 é possível:

<android.support.design.widget.BottomNavigationView
app:labelVisibilityMode="labeled" />

ou você pode configurá-lo programaticamente .

Nota: se você estiver atualizando de uma versão mais antiga da biblioteca de suporte, não se esqueça de aumentar a versão do SDK de compilação. Verifique as versões do libraray de suporte aqui: Versões da Biblioteca de Suporte

No entanto, você ainda poderá receber a mensagem labelVisibilityMode não encontrado ao compilar, se o seu aplicativo depender de versões mais antigas da biblioteca de suporte ao design. Se for esse o caso, tente atualizar para uma versão da dependência fornecida, que depende de pelo menos a versão de 28.0.0-alpha1 da biblioteca de suporte ao design. Se isso não for possível, defina a dependência explicitamente.

Se você usa Gradle

  1. Você pode verificar suas dependências executando a tarefa de dependências e procurar o número da versão com.android.support:design .
  2. Para adicionar dependência de suporte de design explicitamente em seu build.gradle :

    implementação 'com.android.support:design:28.0.0'

Richárd Bogdán
fonte
4

Para resposta atualizada usando o padrão. Atualizar para a biblioteca de design mais recente

implementação "com.android.support:design:28.0.0"

e coloque em seus atributos xml BottomNavigationView

app:itemHorizontalTranslationEnabled="false"

você pode colocá-lo também como programaticamente

bottomNavigationView.setItemHorizontalTranslationEnabled(false);

Você pode encontrar a fonte aqui BottomNavigationView

Espero que isso ajude você.

Lester L.
fonte
De que isso é diferente app:labelVisibilityMode?
wonsuc 25/03/19
@ wonsuc trata da animação de ícone e texto que o item selecionado está animando. Enquanto labelVisibilityMode é para exibir se você deseja mostrar o ícone com texto ou apenas o ícone a ser exibido quando selecionado.
Lester L.
3

Para seu BottomNavigationViewaddapp:labelVisibilityMode="unlabeled"

<android.support.design.widget.BottomNavigationView
        app:menu="@menu/bn_menu"
        android:layout_height="56dp"
        android:layout_width="match_parent"
        app:labelVisibilityMode="unlabeled">

</android.support.design.widget.BottomNavigationView>

o que resulta nos seguintes

Exibição de navegação inferior do Android Desativar texto e mudança

Tudo é muito
fonte
3

É muito simples, basta adicionar uma propriedade no BottomNaviationView

app:labelVisibilityMode="unlabeled"
Nevil Ghelani
fonte
2

Eu tive um comportamento estranho com BottomNavigationView. Quando eu selecionava qualquer item / fragmento, o fragmento empurra o BottomNavigationView um pouco mais para baixo, para que o texto do BottomNavigationView fique abaixo da tela, para que apenas os ícones fiquem visíveis e o texto oculto ao clicar em qualquer item.

Se você está enfrentando esse comportamento estranho, aqui está a solução. Basta remover

android:fitsSystemWindows="true"

no seu layout raiz do fragmento. Basta remover isso e boom! BottomNavigationView funcionará bem, agora pode ser mostrado com texto e ícone. Eu tinha isso na minha raiz CoordinatorLayout do fragmento.

Também não se esqueça de adicionar

BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

em sua atividade para desativar o modo de mudança. Embora não esteja exatamente relacionado à pergunta, mas ainda assim acho útil.

Kishan Solanki
fonte
1
@ abbath0767 você viu link isso? Pode ser útil para você.
Kishan Solanki
Eu pensei que já tinha tentado de tudo, muito obrigado, não esperava encontrar diretamente a resposta que estava procurando.
BekaBot 26/03
1
Prazer @BekaBot
Kishan Solanki
2

Esta é uma biblioteca de terceiros que eu uso e possui muitas opções de personalização, como desativar o modo shift, mostrando apenas ícones, definindo o tamanho dos ícones etc. BottomNavigationViewEx

Pei
fonte
2

Para remover completamente as animações:

Se você também quiser se livrar dessa pequena e irritante animação de margem superior, precisará de mais código de reflexão. Aqui está a solução completa que remove qualquer animação:

@SuppressLint("RestrictedApi")
private static void disableShiftMode(BottomNavigationView view) {
    BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
    try {
        Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
        shiftingMode.setAccessible(true);
        shiftingMode.setBoolean(menuView, false);
        shiftingMode.setAccessible(false);
        for (int i = 0; i < menuView.getChildCount(); i++) {
            BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
            item.setShiftingMode(false);

            Field shiftAmount = item.getClass().getDeclaredField("mShiftAmount");
            shiftAmount.setAccessible(true);
            shiftAmount.setInt(item, 0);
            shiftAmount.setAccessible(false);

            item.setChecked(item.getItemData().isChecked());
        }
    } catch (NoSuchFieldException e) {
        Timber.e(e, "Unable to get fields");
    } catch (IllegalAccessException e) {
        Timber.e(e, "Unable to change values");
    }
}

E certifique-se de adicionar isso ao seu arquivo de configuração proguard:

-keepclassmembers class android.support.design.internal.BottomNavigationMenuView { 
    boolean mShiftingMode; 
}
-keepclassmembers class android.support.design.internal.BottomNavigationItemView { 
    int mShiftAmount;
}
Fred Porciúncula
fonte
O Android 9 (nível da API 28) introduz novas restrições ao uso de interfaces que não são SDK e isso não funcionaria se
visasse
2

atualize sua biblioteca de suporte para 28.0.0.

bottomNav.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);
M Moersalin
fonte
1

Se você estiver usando o suporte: design: 28.0.0, adicione este aplicativo de linha: labelVisibilityMode = "unlabeled" ao seu BottomNavigationView

Omar Hassan
fonte
0

só quero adicionar que acima desse método disableShiftMode também adicione o código abaixo. @SuppressLint ("RestrictedApi")

Aleesha Kanwal
fonte
-1

Você pode usar isso para mostrar texto e ícones no BottomNevigationView para 3 a 5 itens e parar de mudar.

 app:labelVisibilityMode="labeled"

Mas você enfrentará um problema de corte de texto longo no BottmNevigationView para 5 itens. por isso, encontrei boas soluções para interromper a troca de texto, bem como ícones de BottomNevigationView. Você também pode interromper a troca de texto e também os Ícones no BottomNevigationView. Instantâneos de código são fornecidos aqui.

1. Adicione alguma linha de código a BottomNevigationView, como mostrado

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="@dimen/seventy_dp"
    android:layout_semitransparent="true"
    android:background="@color/colorBottomNev"
    android:showAsAction="always|withText"
    app:itemIconTint="@drawable/bottom_navigation_colors"
    app:itemTextColor="@drawable/bottom_navigation_colors"
    app:itemTextAppearanceActive="@style/BottomNavigationViewTextStyle"
    app:itemTextAppearanceInactive="@style/BottomNavigationViewTextStyle"
    app:menu="@menu/bottom_navigation_menu"
    app:labelVisibilityMode="labeled"/>

2. Adicione itens de menu da seguinte forma: -

 <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/action_catalogue"
        android:icon="@drawable/catalogue"
        android:title="@string/catalogue"
        android:enabled="true"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_contracts"
        android:icon="@drawable/contract"
        android:title="@string/contracts"
        android:enabled="true"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_prospects"
        android:icon="@drawable/prospect"
        android:title="@string/prospects"
        android:enabled="true"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_performance"
        android:icon="@drawable/performance"
        android:title="@string/performance"
        android:enabled="true"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_advance"
        android:icon="@drawable/advance"
        android:title="@string/advance"
        android:enabled="true"
        app:showAsAction="ifRoom" />

</menu>

3.Adicione este estilo no arquivo style.xml:

 <style name="BottomNavigationViewTextStyle">
            <item name="android:fontFamily">@font/montmedium</item>
            <item name="android:textSize">10sp</item>
            <item name="android:duplicateParentState">true</item>
            <item name="android:ellipsize">end</item>
            <item name="android:maxLines">1</item>
        </style>

4) Adicione-os na pasta Dimen

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
    <dimen name="design_bottom_navigation_text_size" tools:override="true">10sp</dimen>
    <dimen name="design_bottom_navigation_active_text_size" tools:override="true">10sp</dimen>
</resources>

I teve ajuda de estes ligação e ligar .Você também pode obter obter ajuda estudar esses links.This me ajuda lot.Hope isso também ajudá-lo. Obrigado....

Rahul Kushwaha
fonte