Estou tentando combinar um design como este ..
Observe que a "tonalidade da cor da guia selecionada" é azul, mas o ícone da guia central deve sempre ser o círculo verde com o relógio branco no meio.
Eu tentei várias coisas. Primeiro, tente fazê-lo programaticamente usando um recurso XML de lista de camadas que tinha o recurso PNG de círculo e relógio verde, que não funcionou. Depois, pedi ao designer que me desse o ícone completo (relógio e círculo verde), mas agora estou enfrentando esse problema.
(Não selecionado)
(Selecionado)
Não consigo encontrar os termos corretos para pesquisar no Google para corrigir isso.
No final, preciso que a cor da guia selecionada seja azul, mas preciso que o ícone da guia central seja sempre o ícone real, sem cores adicionais (essencialmente, ele precisa se parecer exatamente com o .png).
PS: Estou usando o Xamarin.Forms, FreshMvvm e o FreshTabbedFONavigationContainer. No entanto, através do Renderer, tenho acesso direto ao BottomNavigationView e a todos os outros componentes nativos do Android. Portanto, a solução não precisa ser uma solução Xamarin. Uma solução java / kotlin também funcionaria e eu posso convertê-la para o Xamarin.
======================
EDITADO:
======================
Então, eu fui muito além usando o código de Andrés Castro abaixo, mas ainda estou tendo o mesmo problema de antes. Usando o código de Andres abaixo, voltei a usar o FontAwesome para os ícones (o que funciona muito bem), mas ao fazer isso, eu precisava usar a LayerDrawable
para criar o ícone da guia central do círculo / ícone.
Então é isso que eu tenho até agora ..
Ícone central não selecionado
Ícone do centro selecionado
Como você pode ver, o ícone central ainda fica cinza quando não selecionado e azul quando selecionado (as cores selecionadas / não selecionadas apropriadas dos outros 4 ícones).
Aqui está o código que tenho até agora referente ao ícone central.
UpdateTabbedIcons
private void UpdateTabbedIcons()
{
for (var i = 0; i < Element.Children.Count; i++) {
var tab = _bottomNavigationView.Menu.GetItem(i);
var element = Element.Children[i];
if (element is NavigationPage navigationPage) {
//if the child page is a navigation page get its root page
element = navigationPage.RootPage;
}
UpdateTabIcon(tab, element);
}
}
UpdateTabIcon
public void UpdateTabIcon(IMenuItem menuItem, Page page)
{
var icon = page?.Icon;
if (icon == null) return;
var drawable = new IconDrawable(Context, icon, "fa-regular-pro-400.ttf");
var element = Element.CurrentPage;
if (element is NavigationPage navigationPage) {
//if the child page is a navigation page get its root page
element = navigationPage.RootPage;
}
if (page is DoNowTabPage) { //Page for center icon
drawable.Color(Helpers.Resources.White.ToAndroid());
var finalDrawable = GetCombinedDrawable(drawable);
menuItem.SetIcon(finalDrawable);
return;
} else if (element == page) {
drawable.Color(BarSelectedItemColor.ToAndroid());
} else {
drawable.Color(BarItemColor.ToAndroid());
}
menuItem.SetIcon(drawable);
}
GetCombinedDrawable
private Drawable GetCombinedDrawable(IconDrawable iconDrawable)
{
var displayMetrics = Resources.DisplayMetrics;
GradientDrawable circleDrawable = new GradientDrawable();
circleDrawable.SetColor(Helpers.Resources.Green.ToAndroid());
circleDrawable.SetShape(ShapeType.Oval);
circleDrawable.SetSize((int)TypedValue.ApplyDimension(ComplexUnitType.Dip, 500, displayMetrics), (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, 500, displayMetrics));
circleDrawable.Alpha = 1;
var inset = (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, 140, displayMetrics);
var bottomInset = (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, 40, displayMetrics);
LayerDrawable finalDrawable = new LayerDrawable(new Drawable[] { circleDrawable, iconDrawable });
finalDrawable.SetLayerHeight(1, iconDrawable.IntrinsicHeight);
finalDrawable.SetLayerWidth(1, iconDrawable.IntrinsicWidth);
finalDrawable.SetLayerInset(1, inset, inset, inset, inset + bottomInset);
finalDrawable.SetLayerInsetBottom(0, bottomInset);
finalDrawable.ClearColorFilter();
return finalDrawable;
}
Como você pode ver no GradientDrawable
que eu estou criando para o círculo, estou configurando a cor para a minha cor verde (eu tenho uma classe personalizada chamada Resources Resources
.. que não é a classe Android ).
Então é aí que eu estou preso. Estou definindo o círculo que pode ser desenhado para ter uma cor verde, mas uma vez no BottomNavigationView, a cor sempre corresponde às cores não selecionadas / selecionadas dos outros ícones.
Esperando superar esta edição final. Obrigado por qualquer ajuda.
_bottomNavigationView.ItemIconTintList = null;
Respostas:
O BottomNavigationView é dolorosamente mais difícil do que sua implementação no iOS. Eu fiz algumas pesquisas para ver se o que você estava perguntando era possível e, quando o vi no Android, comecei a pensar em maneiras de fazer isso acontecer.
Para implementar seu último desafio, você precisaria alterar programaticamente a tonalidade / cor selecionada sempre, dependendo do índice da visualização de navegação inferior.
fonte
Como você tem acesso à visualização de navegação inferior, basta "redesenhar" a barra de ferramentas inferior sempre que alternar as páginas. Fizemos algo semelhante e não percebemos nenhum problema de desempenho.
Você primeiro deseja monitorar as alterações de página assinando a alteração de página dentro
OnElementChanged
Dentro,
ElementOnCurrentPageChanged
você pode percorrer cada página e obter o item de menu dessa páginaNo nosso caso, usamos ícones de fonte para desenhar os ícones e definir as cores todas as vezes.
Também tivemos que substituir o OnAttachedToWindow para garantir que os ícones fossem redesenhados ao retornar ao aplicativo de diferentes estados.
Você precisará modificar isso alguns para se adequar ao seu caso de uso, mas acho que esse método deve realizar o que você está procurando.
fonte
você pode usar imagens SVG, criar seu próprio atributo de cor e criar um seletor extraível para o ícone central, bem como outro ícone de exibição de navegação inferior, como abaixo:
no arquivo colors.xml
no arquivo attrs.xml
no arquivo de imagem SVG
substitua o valor da cor codificada pelo seu atributo
e não se esqueça de tornar o seletor extraível
fonte
Tente usar o DST no modo tonalidade , que simplesmente ignorará a tonalidade.
Adicione esta linha ao seu método
GetCombinedDrawable()
Se isso não funcionar, tente o seguinte:
fonte
Eu posso ajudá-lo com isso :
Este é um TabLayout personalizado, você pode ver que eu estende a classe TabLayout, quando o TabLayout é criado, estou chamando o método initItems que addTab e define uma exibição personalizada para ele.
O getTabView retorna a exibição inflada, como você pode ver com este
Se você precisar
depois de inflar a vista, você pode obter seu elemento de vista com
Você pode verificar se a visualização está selecionada com o booleano selecionado. Para o seu caso, você precisa ignorar a opção de cores quando o índice é central.
Apenas uma coisa quando você clica em um ícone do TabLayout, não se esqueça de chamar o
Se você não fizer isso, a imagem não será redesenhada
fonte
Solução
Adicione itens de Navegação espacial.
Use
initWithSaveInstanceState(savedInstanceState)
eoverride onSaveInstanceState
se desejar manter a posição do item selecionado e o crachá na rotação do dispositivofonte