¿Cómo personalizar el fondo del elemento y el color del texto del elemento dentro de NavigationView?

Respuestas:

4

Con la biblioteca de componentes de materiales puede utilizar estos atributos:

  • app:itemShapeFillColor: color del elemento de fondo
  • app:itemIconTint: tinte de icono
  • app:itemTextColor: color de texto

En el diseño:

<com.google.android.material.navigation.NavigationView
    app:itemShapeFillColor="@color/shape_selector"
    app:itemIconTint="@color/icon_tint_selector"
    app:itemTextColor="@color/text_color_selector"
    ../>

En un estilo personalizado:

<style name="..." parent="Widget.MaterialComponents.NavigationView" >
   <item name="itemShapeFillColor">@color/shape_selector</item>
   <item name="itemIconTint">@color/icon_tint_selector</item>
   <item name="itemTextColor">@color/text_color_selector</item>
</style>

Para el itemIconTinty itemTextColorpuedes usar un selector como este:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:color="?attr/colorPrimary" android:state_checked="true"/>
  <item android:alpha="0.38" android:color="?attr/colorOnSurface" android:state_enabled="false"/>
  <item android:color="?attr/colorOnSurface"/>
</selector>

Para el itemShapeFillColorpuedes usar un selector como:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:alpha="0.12" android:color="?attr/colorPrimary" android:state_activated="true"/>
  <item android:alpha="0.12" android:color="?attr/colorPrimary" android:state_checked="true"/>
  <item android:color="@android:color/transparent"/>
</selector>

Solo una nota final . Preste atención al uso de itemBackground.
Está configurado para @nullusar un fondo con forma generado programáticamente por NavigationViewcuándo itemShapeAppearancey / o itemShapeAppearanceOverlayestá configurado ( comportamiento predeterminado ).
Este fondo se diseña utilizando los itemShape*atributos.
La configuración itemBackgroundsobrescribirá el fondo programático y hará que los valores establecidos en los atributos itemShape * sean ignorados.

ingrese la descripción de la imagen aquí

Gabriele Mariotti
fuente
131

itemBackground, itemIconTinty itemTextColorson atributos xml simples que se pueden configurar, aunque debe usar un prefijo personalizado en lugar de android:uno.

Ejemplo

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- Other layout views -->

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:itemBackground="@drawable/my_ripple"
        app:itemIconTint="#2196f3"
        app:itemTextColor="#009688"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/drawer_view" />

</android.support.v4.widget.DrawerLayout>

Nota: En este caso, el color del texto, el tinte del icono y el fondo son estáticos. Si desea cambiar el color del texto (por ejemplo, rosa cuando está desmarcado y verde azulado cuando está marcado) debe usar un ColorStateList.

Ejemplo

Cree un nuevo archivo * .xml en /res/color(llamémoslo state_list.xml ) con el siguiente contenido:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- This is used when the Navigation Item is checked -->
    <item android:color="#009688" android:state_checked="true" />
    <!-- This is the default text color -->
    <item android:color="#E91E63" />
</selector>

y luego simplemente haga referencia a él así: app:itemTextColor="@color/state_list"

Lo mismo vale para itemIconTint. itemBackgroundespera una identificación de recurso. Consulte también los documentos .

contrarrestar
fuente
1
para el fondo del elemento en el elemento marcado, solo use <item name = "colorControlHighlight"> # 123456 </item>
Xan
1
Eso es cierto, pero esto también podría cambiar el color de otras vistas, como EditTextal menos si lo define en su Tema global.
reverso
3
¿Alguien tiene problemas al configurar app:itemBackground="@drawable/my_ripple"? Me sucede que cuando presiono un elemento, el que está en la parte inferior refleja el efecto dominó en lugar del que estoy presionando.
Javier Mendonça
@JavierMendonca He experimentado lo mismo, pero no conozco una solución para este cajero automático; lo más probable es que se trate de un error, pero tal vez valga la pena hacer una pregunta separada para este problema específico.
Revés
3
Recuerde que para presionar para que funcione, debe cambiarlo de android: state_checked a android: state_pressed.
Programista
97

NavigationDrawer (NavigationView) tiene tres opciones para la configuración de elementos marcados / seleccionados.

app:itemIconTint="@color/menu_text_color" //icon color
app:itemTextColor="@color/menu_text_color" //text color
app:itemBackground="@drawable/menu_background_color" //background

Color de icono y texto

Las dos primeras opciones (icono y texto) necesitan un recurso de lista de estado de color : https://developer.android.com/guide/topics/resources/color-list-resource.html .

Dicho menu_text_colorrecurso debe crearse en res / color . El contenido de este archivo debe tener un aspecto similar a:

<!-- res/color/menu_text_color.xml -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:color="@color/colorWhite" android:state_checked="true" />
  <item android:color="@color/colorBlack" android:state_checked="false"/>
</selector>
  • @color/colorWhite - recurso de color utilizado para el artículo marcado

  • @color/colorBlack - recurso de color utilizado para el elemento sin marcar

He creado un recurso para ambos, pero es posible crear dos archivos separados: uno para texto y otro para icono.

Fondo (itemBackground)

La opción de fondo necesita un recurso dibujable en lugar de color, cada intento de establecer el color terminará con una excepción. El recurso dibujable debe crearse en res / drawable y su contenido debe ser similar a:

<!-- res/drawable/menu_background_color.xml -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@android:color/transparent"  android:state_checked="false"/>
  <item android:drawable="@color/colorPrimary" android:state_checked="true"/>
</selector>

No es necesario crear ningún elemento de diseño que simule el color (en otras soluciones vi tales propuestas, tal vez para la versión sdk anterior), el color se puede usar en este archivo directamente. En este archivo de ejemplo, estoy usando un color transparente para el elemento no marcado y colorPrimarypara el elemento marcado.

Solución de problemas y notas importantes

  • En el recurso de fondo, utilice siempre state_checked = "false" en lugar del predeterminado, con el color predeterminado no funcionará
  • Para el menú creado dinámicamente / programáticamente, recuerde establecer los elementos como marcables :

Ejemplo de código (agregar elemento de menú dinámico):

  menu.add(group_id, item_id, Menu.NONE, item_name).setCheckable(true).setChecked(false);

Si los elementos no se configuran como comprobables, el fondo no funcionará (el color del texto y el icono sorprendente funcionarán como se esperaba).

Maciej Sikora
fuente
1
buena respuesta, pero prefiero crear un tema para la vista de navegación. ¿Qué atributo necesito anular?
Xan
@MaciejSikora ¡Me salvas la vida! ¡Los amo hombres! Cásate conmigo :)
Krzysiek
Esto es lo más importante, ya que nada funciona. remember to set items as checkable. Gracias por mencionar esto, lo que nadie hizo.
SimpleGuy
8

Usar colorControlHighlight es una buena solución para mí. Tenga en cuenta que con la biblioteca de soporte más reciente, puede definir un tema (no solo el estilo) para cada widget; por ejemplo, puede definir colorControlHighlight en el tema NavigationView y esto no se aplicará al resto de widgets.

Mimmo Grottoli
fuente
3
respuesta perfecta, pero ¿qué atributo necesito anular en el tema NavigationView para controlar el fondo, el color del texto y el color del icono?
Xan
sí, claro, crea un estilo con, <item name="android:colorControlHighlight">@color/navigationDrawerTextNight</item>pero ¿cómo se aplica al texto del elemento del menú? itemTextColorno existe en un estilo
Someone Somewhere
6

Si desea cambiar solo un color de elemento de menú de su actividad en función de los eventos, consulte este blog de HANIHASHEMI:

https://hanihashemi.com/2017/05/06/change-text-color-of-menuitem-in-navigation-drawer/

private void setTextColorForMenuItem(MenuItem menuItem, @ColorRes int color) {
  SpannableString spanString = new SpannableString(menuItem.getTitle().toString());
  spanString.setSpan(new ForegroundColorSpan(ContextCompat.getColor(this, color)), 0, spanString.length(), 0);
  menuItem.setTitle(spanString);
}

Método de llamada

setTextColorForMenuItem(item, R.color.colorPrimary);

Si trabaja con Xamarin Android, intente esto:

private void SetTextColorForMenuItem(IMenuItem menuItem, Android.Graphics.Color color)
        {
            SpannableString spanString = new SpannableString(menuItem.TitleFormatted.ToString());
            spanString.SetSpan(new ForegroundColorSpan(color), 0, spanString.Length(), 0);
            menuItem.SetTitle(spanString);
        }

Método de llamada:

SetTextColorForMenuItem(navigationView.Menu.GetItem(0), Android.Graphics.Color.OrangeRed);
Jhon
fuente
5

Puede usar programáticamente este código:

int[][] states = new int[][] {
    new int[] { android.R.attr.state_enabled}, // enabled
    new int[] {-android.R.attr.state_enabled}, // disabled
    new int[] {-android.R.attr.state_checked}, // unchecked
    new int[] { android.R.attr.state_pressed}  // pressed
};

int[] colors = new int[] {
    Color.BLACK,
    Color.RED,
    Color.GREEN,
    Color.BLUE
};

ColorStateList myList = new ColorStateList(states, colors);

  nav_view.setItemIconTintList(myList);
Ahmad Aghazadeh
fuente
3

Ahora, en la vista de navegación, también puede proporcionar su propia vista de elementos. Con lo nuevo appcompat-v7:23.1.0puedes

establezca vistas personalizadas para elementos a través de la aplicación: actionLayout o usando MenuItemCompat.setActionView ().

View view = View.inflate(context, R.layout.your_custom_nav_layout_item, null);
MenuItemCompat.setActionView(menuItem, view); 

De esta manera, puede crear su propio diseño con TextView y cambiarlo backgrounds/colors/fontscomo desee. Espero que esto haya sido útil :) Fuente

hkop
fuente
0

Si desea hacer esto mediante programación:

Basado en la respuesta de Jhon:

Puede usar la extensión Kotlin de esta manera:

fun NavigationView.setTextColorForMenuItems(@ColorInt color: Int) {
    for (i: Int in 0 until menu.size()) {
        val menuItem = menu.getItem(i)
        val spanString = SpannableString(menuItem.title.toString())
        spanString.setSpan(ForegroundColorSpan(color), 0, spanString.length, 0)
        menuItem.title = spanString
    }
}

Luego llame

nav_view.setTextColorForMenuItems(Color.BLACK)
Alex Smith
fuente
-1

Puedes hacerlo usando la siguiente declaración:

navigationView.setItemBackground(ContextCompat.getDrawable(CustomerHomeActivity.this, R.color.transparent));
Sohaib Khalid
fuente