Estoy intentando hacer coincidir un diseño como este ...
Observe que el "tinte de color de la pestaña seleccionada" es azul, pero el icono de la pestaña central siempre debe ser el círculo verde con el reloj blanco en el medio.
He intentado varias cosas. Primero intente hacerlo mediante programación usando un recurso XML de lista de capas que tenga el círculo verde y el recurso PNG del reloj, que no funcionó en absoluto. Luego acabo de pedirle al diseñador que me dé el ícono completo (reloj y círculo verde), pero ahora me encuentro con este problema.
(Sin seleccionar)
(Seleccionado)
No logro encontrar los términos correctos para buscar en Google para solucionar esto.
Al final, necesito que el color de la pestaña seleccionada sea azul, pero necesito que el ícono de la pestaña central sea siempre el ícono real sin coloración adicional (esencialmente necesita verse exactamente como el .png).
PD: Estoy usando Xamarin.Forms, FreshMvvm y FreshTabbedFONavigationContainer. Sin embargo, a través del Renderer, tengo acceso directo a BottomNavigationView y a todos los demás componentes nativos de Android. Por lo tanto, la solución no tiene que ser una solución de Xamarin. Una solución java / kotlin también funcionaría y puedo convertirla a Xamarin.
======================
EDITADO:
======================
Así que he llegado mucho más lejos usando el código de Andrés Castro a continuación, pero todavía tengo el mismo problema que antes. Usando el código de Andrés a continuación, volví a usar FontAwesome para los íconos (que funciona muy bien), pero al hacerlo significa que necesitaba usar unLayerDrawable
para crear el ícono de la pestaña central del círculo / ícono.
Así que esto es lo que tengo hasta ahora ...
Icono de centro no seleccionado
Icono del centro seleccionado
Como puede ver, el ícono central sigue siendo gris cuando no está seleccionado y azul cuando está seleccionado (los colores apropiados seleccionados / no seleccionados de los otros 4 íconos).
Aquí está el código que tengo hasta ahora relacionado con el icono del centro.
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 puedes ver en el GradientDrawable
que estoy creando para el círculo, estoy configurando su color a mi color Verde (tengo una clase personalizada llamada Recursos ... esa no es la Resources
clase de Android ).
Entonces ahí es donde estoy atrapado. Estoy configurando el círculo dibujable para que tenga un color verde, pero una vez en la Vista de navegación inferior, su color siempre coincide con los colores no seleccionados / seleccionados de los otros iconos.
Con la esperanza de superar este último problema. Gracias por cualquier ayuda.
_bottomNavigationView.ItemIconTintList = null;
Respuestas:
BottomNavigationView es dolorosamente más difícil que su implementación de iOS. Investigué un poco para ver si lo que preguntabas era posible, y luego, cuando lo vi en Android, comencé a pensar en formas de hacerlo realidad.
Para implementar su último desafío, deberá cambiar mediante programación el tono / color seleccionado cada vez, según el índice de la vista de navegación inferior.
fuente
Como tiene acceso a la vista de navegación inferior, puede "volver a dibujar" la barra de herramientas inferior cada vez que cambie de página. Hicimos algo similar y no notamos ningún problema de rendimiento.
Primero querrá monitorear los cambios de página suscribiéndose al cambio de página dentro
OnElementChanged
Luego, dentro
ElementOnCurrentPageChanged
puede atravesar cada página y obtener el elemento de menú para esa páginaEn nuestro caso, utilizamos iconos de fuente, así que dibujamos los iconos y configuramos los colores cada vez.
También tuvimos que anular OnAttachedToWindow para asegurarnos de que los iconos se volvieran a dibujar al volver a la aplicación desde diferentes estados.
Tendrá que modificar esto para que se ajuste a su caso de uso, pero creo que este método debería lograr lo que está buscando.
fuente
puede usar imágenes SVG y hacer su propio atributo de color y hacer un selector dibujable para el icono central, así como otro icono de vista de navegación inferior, como se muestra a continuación:
en el archivo colors.xml
en el archivo attrs.xml
en archivo de imagen SVG
reemplace el valor de color codificado con su atributo
y no olvides hacer que el selector sea dibujable
fuente
Intente utilizar el modo de tinte DST , que simplemente ignorará el tinte.
Agregue esta línea a su método
GetCombinedDrawable()
Si esto no funciona, intente esto:
fuente
Te puedo ayudar con esto:
Este es un TabLayout personalizado que puede ver que estoy extiende la clase TabLayout, cuando se crea el TabLayout, llamo al método initItems que agregaTab y establece una vista personalizada para él.
GetTabView devuelve la vista inflada como puede ver con esto
Si lo necesitas
después de inflar la vista, puede obtener su elemento de vista con
Puede verificar si la vista está seleccionada con el valor booleano seleccionado; para su caso, debe ignorar el cambio de color cuando el índice es el central.
Solo una cosa cuando hace clic en un icono de TabLayout no olvide llamar al
Si no lo hace, la imagen no se volverá a dibujar
fuente
Solución
Añadir elementos de navegación espacial.
Utilizar
initWithSaveInstanceState(savedInstanceState)
yoverride onSaveInstanceState
si desea mantener la posición del elemento seleccionado y la insignia en la rotación del dispositivofuente