Pregunta Diseños de notificación personalizados y colores de texto


Mi aplicación muestra algunas notificaciones y, dependiendo de las preferencias del usuario, puede usar un diseño personalizado en una notificación. Funciona bien, pero hay un pequeño problema: colores de texto. Stock Android y casi todos los skins del fabricante usan texto negro sobre un fondo claro para el texto de notificación, pero Samsung no: su menú desplegable de notificaciones tiene un fondo oscuro y el texto en el diseño de notificación predeterminado es blanco.

Esto causa un problema: las notificaciones que no usan diseños elegantes aparecen bien, pero la que usa un diseño personalizado es difícil de leer porque el texto es negro en lugar del blanco predeterminado. Incluso el documentación oficial solo establece un #000 color para un TextView, así que no pude encontrar ningún puntero allí.

Un usuario tuvo la amabilidad de tomar una captura de pantalla del problema:

Screenshot

Asi que ¿Cómo uso el color de texto de notificación predeterminado del dispositivo? en mis diseños? Prefiero no comenzar a modificar dinámicamente el color del texto en función del modelo de teléfono, ya que requiere mucha actualización y las personas con ROM personalizadas pueden tener el problema, dependiendo de la máscara que estén usando.


75
2018-02-01 19:57


origen


Respuestas:


La solución de Malcolm funciona bien con API> = 9. Aquí está la solución para una API más antigua:

El truco es crear el objeto de notificación estándar y luego recorrer el valor predeterminado contentView creado por Notification.setLatestEventInfo(...). Cuando encuentre el TextView correcto, simplemente obtenga el tv.getTextColors().getDefaultColor().

Aquí está el código que extrae el color del texto predeterminado y el tamaño del texto (en píxeles de densidad escalada - sp).

private Integer notification_text_color = null;
private float notification_text_size = 11;
private final String COLOR_SEARCH_RECURSE_TIP = "SOME_SAMPLE_TEXT";

private boolean recurseGroup(ViewGroup gp)
{
    final int count = gp.getChildCount();
    for (int i = 0; i < count; ++i)
    {
        if (gp.getChildAt(i) instanceof TextView)
        {
            final TextView text = (TextView) gp.getChildAt(i);
            final String szText = text.getText().toString();
            if (COLOR_SEARCH_RECURSE_TIP.equals(szText))
            {
                notification_text_color = text.getTextColors().getDefaultColor();
                notification_text_size = text.getTextSize();
                DisplayMetrics metrics = new DisplayMetrics();
                WindowManager systemWM = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
                systemWM.getDefaultDisplay().getMetrics(metrics);
                notification_text_size /= metrics.scaledDensity;
                return true;
            }
        }
        else if (gp.getChildAt(i) instanceof ViewGroup)
            return recurseGroup((ViewGroup) gp.getChildAt(i));
    }
    return false;
}

private void extractColors()
{
    if (notification_text_color != null)
        return;

    try
    {
        Notification ntf = new Notification();
        ntf.setLatestEventInfo(this, COLOR_SEARCH_RECURSE_TIP, "Utest", null);
        LinearLayout group = new LinearLayout(this);
        ViewGroup event = (ViewGroup) ntf.contentView.apply(this, group);
        recurseGroup(event);
        group.removeAllViews();
    }
    catch (Exception e)
    {
        notification_text_color = android.R.color.black;
    }
}

Llamada extractColors es decir. en onCreate () de su servicio. Luego, cuando está creando la notificación personalizada, el color y el tamaño de texto que desea están en notification_text_color y notification_text_size:

Notification notification = new Notification();
RemoteViews notification_view = new RemoteViews(getPackageName(), R.layout.notification);       
notification_view.setTextColor(R.id.label, notification_text_color);
notification_view.setFloat(R.id.label, "setTextSize", notification_text_size);

57
2017-09-06 13:21



La solución es usar estilos incorporados. El estilo que necesita se llama TextAppearance.StatusBar.EventContent en Android 2.3 y Android 4.x. En las notificaciones de material de Android 5.x, use varios otros estilos: TextAppearance.Material.Notification, TextAppearance.Material.Notification.Titley TextAppearance.Material.Notification.Line2. Simplemente configure la apariencia del texto apropiado para la vista de texto, y obtendrá los colores necesarios.

Si está interesado en cómo he llegado a esta solución, aquí está mi rastro de migas de pan. Los extractos del código están tomados de Android 2.3.

  1. Cuando usas Notification y establecer el texto utilizando medios incorporados, la siguiente línea crea el diseño:

    RemoteViews contentView = new RemoteViews(context.getPackageName(),
            com.android.internal.R.layout.status_bar_latest_event_content);
    
  2. El diseño mencionado contiene lo siguiente View que es responsable de ver el texto de notificación:

    <TextView android:id="@+id/text"
        android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:singleLine="true"
        android:ellipsize="marquee"
        android:fadingEdge="horizontal"
        android:paddingLeft="4dp"
        />
    
  3. Entonces la conclusión es que el estilo necesario es TextAppearance.StatusBar.EventContent, que definición se ve así:

    <style name="TextAppearance.StatusBar.EventContent">
        <item name="android:textColor">#ff6b6b6b</item>
    </style>
    

    Debe tener en cuenta que este estilo no hace referencia a ninguno de los colores incorporados, por lo que la forma más segura es aplicar este estilo en lugar de un color incorporado.

Una cosa más: antes de Android 2.3 (API Nivel 9), no había ni estilos ni colores, solo había valores codificados. Si por alguna razón tiene que admitir versiones antiguas, consulte el respuesta por Gaks .


80
2018-02-08 15:50



Aquí hay una solución para cualquier versión de SDK que use solo recursos.

res / values ​​/ styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="NotificationTitle">
      <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
      <item name="android:textStyle">bold</item>
    </style>
    <style name="NotificationText">
      <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
    </style>
</resources>

res / values-v9 / styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="NotificationText" parent="android:TextAppearance.StatusBar.EventContent" />
    <style name="NotificationTitle" parent="android:TextAppearance.StatusBar.EventContent.Title" />
</resources>

res / layout / my_notification.xml

...
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="title"
    style="@style/NotificationTitle"
    />
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="text"
    style="@style/NotificationText"
    />
...

P.S: los valores codificados se usan para 2.2-. Por lo tanto, pueden surgir problemas con algunos firmwares antiguos raros.


16
2018-01-06 04:58



Para 2.3+ (desde Documentación de Android)

Usa el estilo android:TextAppearance.StatusBar.EventContent.Title para el texto principal.

Usa el estilo android:TextAppearance.StatusBar.EventContent para el texto secundario.

Para 2.2-, haz lo que Gaks sugirió en otra respuesta a este hilo.

Si quieres compilar contra 2.2 y soportar 2.3+, y admitir toda la variedad de dispositivos que existen, la solución de Gaks es la única que conozco.

Por cierto, lo que Google sugirió sobre el uso del valor ?android:attr/textColorPrimary para 2.2-, no está funcionando. Solo inténtalo usando el emulador. El camino de Gaks es la única forma.

Más recursos: Esta y esta No funcionan.


13
2017-12-06 19:21



Debe usar los colores especificados en android.R.color

Por ejemplo: android.R.color.primary_text_light

Se supone que los desarrolladores de ROM personalizados y los diseñadores de la piel de Android deben actualizarlos para que los colores de su aplicación puedan estar en línea con el resto del sistema. Esto incluye asegurarse de que su texto se muestre correctamente en todo el sistema.


2
2018-02-02 02:40



He encontrado una solución muy simple que cambia directamente el nombre del atributo proporcionado por Android.

Como puedes ver en este tutorial: http://www.framentos.com/android-tutorial/2012/02/20/how-to-create-a-custom-notification-on-android/

Solo necesitas usar un atributo diferente:

<item name="android:textColor">?android:attr/textColorPrimaryInverse</item>

¡Espero que esto le pueda ayudar!


2
2018-02-21 18:49



Mirando estas instrucciones: http://developer.android.com/guide/topics/ui/notifiers/notifications.html#CustomExpandedView  Si configura su color de fondo para el contenedor LinearLayout, puede tener sus colores en notificación para el texto y el fondo.

Si la aplicación iniciadora define el color predeterminado para el texto de notificación, no podrá recuperarlo de la configuración predeterminada de Android a menos que el iniciador esté filtrando esta información.

Sin embargo, ¿ha intentado eliminar esta línea de android: textColor = "# 000" de su diseño para que pueda obtener automáticamente el color predeterminado?


1
2018-02-06 05:34



La solución de @Malckom no me ayudó en Lolipop con el fondo de notificación oscuro debido a TextAppearance.Material.Notification.Title es un sistema de color codificado. La solución de @grzaks sí, pero con algunos cambios dentro del proceso de creación de notificaciones:

NotificationCompat.Builder mBuilder =
    new NotificationCompat.Builder(this)
                          .setContentTitle(NOTIFICATION_TITLE_TIP)
                          .setContentText(NOTIFICATION_TEXT_TIP);
Notification ntf = mBuilder.build();
// ...
if (NOTIFICATION_TEXT_TIP.equals(szText)) {
    notification_text_color = text.getTextColors().getDefaultColor();
} else {
    if (NOTIFICATION_TITLE_TIP.equals(szText)) {
        notification_title_color = text.getTextColors().getDefaultColor();
    }
}
// ...

0
2018-03-05 12:51



Sé que es una vieja pregunta, pero podría ayudar a otra persona; ) Lo hago en mi aplicación y funciona perfectamente en algunas líneas:

    RemoteViews notificationView = new RemoteViews(context.getPackageName(), R.layout.notification_layout);

    if (SDK >= LOLLIPOP) {

            TextView textView = new TextView(context);
            textView.setTextAppearance(context, android.R.style.TextAppearance_Material_Notification_Title);

            notificationView.setTextColor(R.id.title, textView.getCurrentTextColor());
            notificationView.setFloat(R.id.title, "setTextSize", textView.getTextSize());

            textView.setTextAppearance(context,android.R.style.TextAppearance_Material_Notification_Line2);

            notificationView.setTextColor(R.id.contentText,textView.getCurrentTextColor());
            notificationView.setFloat(R.id.contentText,"setTextSize",textView.getTextSize());

            textView = null;

    }

0
2018-01-01 22:38