Frage Benutzerdefinierte Benachrichtigungslayouts und Textfarben


Meine Anwendung zeigt einige Benachrichtigungen an, und abhängig von den Benutzereinstellungen verwendet sie möglicherweise ein benutzerdefiniertes Layout in einer Benachrichtigung. Es funktioniert gut, aber es gibt ein kleines Problem - Textfarben. Stock Android und fast alle Hersteller Skins verwenden schwarzen Text vor einem hellen Hintergrund für Benachrichtigungstext, aber Samsung nicht: ihre Benachrichtigung Pulldown hat einen dunklen Hintergrund und der Text in der Standard-Benachrichtigungslayout ist weiß.

Dies führt zu einem Problem: Die Benachrichtigungen, die keine ausgefallenen Layouts verwenden, sind gut sichtbar, aber die, die ein benutzerdefiniertes Layout verwendet, ist schwer zu lesen, da der Text schwarz statt des Standard-Weiß ist. Sogar die offizielle Dokumentation setzt gerade ein #000 Farbe für ein TextViewAlso konnte ich dort keine Hinweise finden.

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

Screenshot

Damit Wie verwende ich die standardmäßige Benachrichtigungstextfarbe vom Gerät? in meinen Layouts? Ich würde lieber nicht beginnen, die Textfarbe basierend auf dem Telefonmodell dynamisch zu ändern, da dies eine Menge Aktualisierungen erfordert und Leute mit benutzerdefinierten ROMs das Problem je nach verwendetem Skin immer noch bekommen können.


75
2018-02-01 19:57


Ursprung


Antworten:


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 den Standardwert zu durchlaufen contentView erstellt von Notification.setLatestEventInfo(...). Wenn Sie die richtige TextView finden, holen Sie sich einfach die tv.getTextColors().getDefaultColor().

Hier ist der Code, der die standardmäßige Textfarbe und Textgröße (in skalierten Dichtepixeln - 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;
    }
}

Anruf extractColors dh. in onCreate () Ihres Dienstes. Wenn Sie die benutzerdefinierte Benachrichtigung erstellen, sind die gewünschte Farbe und die gewünschte Textgröße enthalten 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);

57
2017-09-06 13:21



Die Lösung besteht darin, integrierte Stile zu verwenden. Der Stil, den Sie brauchen, heißt TextAppearance.StatusBar.EventContent in Android 2.3 und Android 4.x. In Android 5.x-Materialbenachrichtigungen werden verschiedene andere Stile verwendet: TextAppearance.Material.Notification, TextAppearance.Material.Notification.Title, und TextAppearance.Material.Notification.Line2. Legen Sie einfach die entsprechende Textdarstellung für die Textansicht fest, und Sie erhalten die erforderlichen Farben.

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

  1. Wenn Sie verwenden Notification und legen Sie den Text mithilfe von integrierten Mitteln, die folgende Zeile erstellt 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 folgendes View welches für das Anzeigen von Benachrichtigungstext zuständig 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. Also die Schlussfolgerung ist, dass der benötigte Stil ist TextAppearance.StatusBar.EventContent, welche Definition sieht so aus:

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

    Sie sollten hier beachten, dass dieser Stil keine der eingebauten Farben referenziert, also ist der sicherste Weg, diesen Stil anstelle einer eingebauten Farbe anzuwenden.

Noch eine Sache: Vor Android 2.3 (API Level 9) gab es weder Stile noch Farben, es gab nur fest codierte Werte. Wenn Sie solche alten Versionen aus irgendeinem Grund unterstützen müssen, lesen Sie bitte die Antwort von Gaks .


80
2018-02-08 15:50



Hier ist die 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 / Werte-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: Hartcodierte Werte werden für 2.2- verwendet. So können Probleme mit einigen seltenen alten benutzerdefinierten Firmwares auftreten.


16
2018-01-06 04:58



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

Verwenden Sie den Stil android:TextAppearance.StatusBar.EventContent.Title für den primären Text.

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

Für 2.2-, mach was Schlug Gaks vor in einer anderen Antwort auf diesen Thread.

Wenn Sie gegen 2.2 kompilieren und 2.3 + unterstützen möchten und die gesamte Gerätevielfalt unterstützen, ist die Lösung von Gaks die einzige, die ich kenne.

Übrigens, was Google vorgeschlagen hat, um den Wert zu verwenden ?android:attr/textColorPrimary für 2.2-, funktioniert nicht. Probieren Sie es einfach mit dem Emulator. Gaks 'Art ist der einzige Weg.

Mehr Ressourcen: Dies und Dies arbeite nicht.


13
2017-12-06 19:21



Sie sollten die in angegebenen Farben verwenden android.R.color

Beispielsweise: android.R.color.primary_text_light

Benutzerdefinierte ROM-Entwickler und Android-Skin-Designer sollten diese aktualisieren, damit die Farben Ihrer App dem Rest des Systems entsprechen. Dazu gehört, dass Ihr Text im gesamten System ordnungsgemäß angezeigt wird.


2
2018-02-02 02:40



Ich habe eine sehr einfache Lösung gefunden, die den Namen des von Android bereitgestellten Attributs direkt ändert.

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!


2
2018-02-21 18:49



Schau dir diese Anleitung an: http://developer.android.com/guide/topics/ui/notifiers/notifications.html#CustomExpandedView  Wenn Sie Ihre Hintergrundfarbe für den LinearLayout-Container festlegen, können Sie Ihre Farben in der Benachrichtigung für Text und Hintergrund anzeigen lassen.

Wenn die Standardfarbe für den Benachrichtigungstext durch die Launcher-Anwendung definiert ist, können Sie sie nicht aus den Standardeinstellungen von Android abrufen, es sei denn, der Launcher teilt diese Informationen mit.

Haben Sie jedoch versucht, diese Linie Android: textColor = "# 000" aus Ihrem Layout zu entfernen, so dass es automatisch die Standardfarbe bekommen kann?


1
2018-02-06 05:34



Lösung von @Malckom hat mir bei Lolipop mit dunklem Benachrichtigungshintergrund wegen TextAppearance.Material.Notification.Title nicht geholfen ist eine systemfest codierte Farbe. Lösung von @grzaks tat, aber mit einigen Änderungen im Prozess der Erstellung von Benachrichtigungen:

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



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

    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