wake-up-neo.com

Benutzerdefinierte Benachrichtigungslayouts und Textfarben

In meiner Anwendung werden einige Benachrichtigungen angezeigt. Abhängig von den Benutzereinstellungen wird möglicherweise ein benutzerdefiniertes Layout in einer Benachrichtigung verwendet. Es funktioniert gut, aber es gibt ein kleines Problem - Textfarben . Stock Android und fast alle Hersteller-Skins verwenden schwarzen Text vor hellem Hintergrund für Benachrichtigungstexte, Samsung jedoch nicht: Der Benachrichtigungs-Pulldown wird dunkel hinterlegt und der Text im Standard-Benachrichtigungslayout ist weiß .

Dies führt also zu einem Problem: Benachrichtigungen, die keine ausgefallenen Layouts verwenden, werden gut angezeigt, aber die Benachrichtigungen, die ein benutzerdefiniertes Layout verwenden, sind schwer zu lesen, da der Text schwarz statt des Standardweiß ist. Sogar die offizielle Dokumentation setzt nur ein #000 Farbe für ein TextView, daher konnte ich dort keine Hinweise finden.

Ein Benutzer war so freundlich, einen Screenshot des Problems zu machen:

Screenshot

Also wie verwende ich die Standardfarbe für Benachrichtigungstexte vom Gerät in meinen Layouts? Ich würde lieber nicht anfangen, die Textfarbe basierend auf dem Telefonmodell dynamisch zu ändern, da dies eine Menge Aktualisierung erfordert und Benutzer mit benutzerdefinierten ROMs das Problem möglicherweise immer noch haben, abhängig von der verwendeten Skin.

79
Veeti

Die Lösung von Malcolm funktioniert gut mit API> = 9. Hier ist die Lösung für ältere API:

Der Trick besteht darin, das Standardbenachrichtigungsobjekt zu erstellen und dann das von Notification.setLatestEventInfo(...) erstellte Standard-contentView zu durchlaufen. Wenn Sie die richtige Textansicht gefunden haben, rufen Sie einfach die Funktion tv.getTextColors().getDefaultColor() auf.

Hier ist der Code, der die Standardtextfarbe und -größe (in Pixeln mit skalierter Dichte - sp) extrahiert.

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;
    }
}

Rufen Sie extractColors dh auf. in onCreate () Ihres Dienstes. Wenn Sie dann die benutzerdefinierte Benachrichtigung erstellen, befinden sich die gewünschte Farbe und Textgröße in notification_text_color und 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);
59
grzaks

Die Lösung besteht darin, integrierte Stile zu verwenden. Der von Ihnen benötigte Stil heißt TextAppearance.StatusBar.EventContent In Android 2.3 und Android 4.x. In Android= 5.x-Materialbenachrichtigungen verwenden verschiedene andere Stile: TextAppearance.Material.Notification, TextAppearance.Material.Notification.Title Und TextAppearance.Material.Notification.Line2. Stellen Sie einfach die entsprechende Textdarstellung für die Textansicht ein, und Sie erhalten die erforderlichen Farben .

Wenn Sie interessiert sind, wie ich zu dieser Lösung gekommen bin, hier ist meine Spur von Paniermehl. Die Code-Auszüge stammen aus Android 2.3.

  1. Wenn Sie Notification verwenden und den Text mit integrierten Mitteln festlegen, erstellt die folgende Zeile das Layout:

    RemoteViews contentView = new RemoteViews(context.getPackageName(),
            com.Android.internal.R.layout.status_bar_latest_event_content);
    
  2. Das erwähnte Layout enthält das folgende View, das für die Anzeige des Benachrichtigungstextes verantwortlich ist:

    <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. Das Fazit ist also, dass der benötigte Stil TextAppearance.StatusBar.EventContent Ist. Diese Definition sieht folgendermaßen aus:

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

    Sie sollten hier beachten, dass dieser Stil keine der integrierten Farben referenziert. Daher ist es am sichersten, diesen Stil anstelle einiger integrierter Farben anzuwenden.

Eine weitere Sache: Vor Android 2.3 (API Level 9) gab es weder Stile noch Farben, es gab nur fest codierte Werte. Wenn Sie für einige solche alten Versionen unterstützen müssen Grund, siehe die Antwort von Gaks .

81
Malcolm

Hier finden Sie eine Lösung für jede SDK-Version, die nur Ressourcen verwendet.

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: Für 2.2- werden hartcodierte Werte verwendet. Daher können Probleme mit einigen seltenen alten benutzerdefinierten Firmwares auftreten.

17
A-IV

Für 2.3+ (From Android-Dokumentation ):

Verwenden Sie den Stil Android:TextAppearance.StatusBar.EventContent.Title für den Haupttext.

Verwenden Sie den Stil Android:TextAppearance.StatusBar.EventContent für den sekundären Text.

Tun Sie für 2.2-, was schlug Gaks vor in einer anderen Antwort auf diesen Thread.

Wenn Sie mit 2.2 kompilieren und 2.3+ unterstützen möchten und die ganze Vielfalt von Geräten unterstützen möchten, ist die Lösung von Gaks die einzige, die ich kenne.

Übrigens, was Google über die Verwendung des Werts ?android:attr/textColorPrimary für 2.2- funktioniert nicht. Probieren Sie es einfach mit dem Emulator. Gaks Weg ist der einzige Weg.

Weitere Ressourcen: This und this funktionieren nicht.

13

Sie sollten die in Android.R.color Angegebenen Farben verwenden.

Zum Beispiel: Android.R.color.primary_text_light

Benutzerdefinierte ROM Entwickler und Android Skin-Designer sollen diese aktualisieren, damit die Farben Ihrer App mit dem Rest des Systems in Einklang stehen Text wird im gesamten System korrekt angezeigt.

2
Austyn Mahoney

Ich benutze dies für die betreffende TextView:

style="@style/TextAppearance.Compat.Notification.Title"

Es gibt mir weißen Text, wenn der Hintergrund schwarz ist, und schwarzen Text, wenn der Hintergrund weiß ist. Und es funktioniert mindestens so weit wie API 19.

1
Gavin Wright

Ich habe eine sehr einfache Lösung gefunden, bei der der Name des von Android bereitgestellten Attributs direkt geändert wird.

Wie Sie in diesem Tutorial sehen können: http://www.framentos.com/Android-tutorial/2012/02/20/how-to-create-a-custom-notification-on-Android/ =

Sie müssen nur ein anderes Attribut verwenden:

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

Hoffe das kann dir helfen!

1
Mauri

Schauen Sie sich diese Anweisungen an: http://developer.Android.com/guide/topics/ui/notifiers/notifications.html#CustomExpandedView Wenn Sie die Hintergrundfarbe für den LinearLayout-Container festlegen, können Sie haben Ihre Farben in der Benachrichtigung für Text und Hintergrund.

Wenn die Standardfarbe für den Benachrichtigungstext von der Startprogrammanwendung definiert wird, können Sie sie nicht aus den Standardeinstellungen von Android) abrufen, es sei denn, das Startprogramm teilt diese Informationen mit.

Haben Sie jedoch versucht, diese Zeile Android: textColor = "# 000" aus Ihrem Layout zu entfernen, damit sie automatisch die Standardfarbe erhält?

1
Lumis

Ich weiß, es ist eine alte Frage, aber sie könnte jemand anderem helfen. ) Ich mache das in meiner App und das funktioniert in einigen Zeilen perfekt:

    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
Samet

Die Lösung von @Malckom hat mir bei Lolipop mit dunklem Benachrichtigungshintergrund aufgrund von TextAppearance.Material.Notification.Title nicht geholfen. Es handelt sich um eine vom System fest codierte Farbe. Lösung von @grzaks, jedoch mit einigen Änderungen im Benachrichtigungserstellungsprozess:

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
Yurii Solopov

Folgendes hat bei mir funktioniert, um diesen Fehler zu beheben. Fügen Sie styles.xml Folgendes hinzu

    <style name="TextAppearance">
    </style>
    <style name="TextAppearance.StatusBar">
    </style>
    <style name="TextAppearance.StatusBar.EventContent">
        <item name="Android:textColor">#ff6b6b6b</item>
    </style>
    <style name="TextAppearance.StatusBar.EventContent.Info">
        <item name="Android:textColor">#ff6b6b6b</item>
    </style>
0
inder