Set the font/icon color of Notification on Android notification bar to change with background color

Posted by philspliff on Sat, 18 May 2019 09:31:51 +0200

Set the font/button color in the notification bar to change with the background color of the system drop-down menu

This article is about how the Android-side APP can keep the font colors and icons in the Notification in high contrast in the lower menu of different colors, while setting the Notification background to be transparent when it issues a Notification in the menu below.The two articles that benefit from this are Android Custom Notification Notification Adapts Different Background Colors and Notification Bar Set System Font Color.

cause

A common way is to add a background color to the notification.Notification bars with background colors do not blend perfectly into drop-down menus of different colors, although they guarantee the contrast between text and icons.NetEasy Cloud Music has made the background color transparent, and the notification bar font color always has a high contrast, but there is only one set of button icons. When the background color and icon color of the drop-down menu are similar, the buttons will not be obvious enough~The display effect is as shown in the figure:

How can the font and icon colors in the notification be adapted to different phone themes?The article starts with two articles for reference, corresponding to two solutions. Here is a brief description. If you need children's shoes, you can click on the link to see the details.I will focus on the third option to make up for the shortcomings.

Scheme One

principle

Because the text color of the system notification changes with the background color of the drop-down menu (with different themes), this method sets the text color of the custom notification to be the same as that of the system notification to ensure the text contrast.

step

This scenario gives different scenarios for Android versions less than 5.0 and Android versions higher than 5.0. In short, in Android versions less than 5.0, add the following lines in Title and Introduction Introductions in the layout file (.xml) of the notification:

...
    <TextView>
        ...
        android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
        ...
    </TextView>

In versions higher than 5.0, add a line statement to the <TextView>that represents Title in the layout file of the notification:

...
    <TextView>
        ...
        android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"
        ...
    </TextView>

Add a line to the <TextView>that describes the Introduction in the layout file for the notification:

...
    <TextView>
        ...
        android:textAppearance="@android:style/TextAppearance.Material.Notification.Line2"
        ...
    </TextView>

The text color of the custom notification is the same as that of the system notification.

Inadequacies of scenario one

However, this scheme has two shortcomings: Title and Introduction are the same color (usually gray) for scenarios less than 5.0, which is not good if they are required to have different contrast; For scenarios above version 5.0, the limitation of "above version 5.0" is insufficient.

Option 2

principle

Scenario 2 retrieves the font color in the system notification by traversing the viewGroup of the system notification, then decides whether the font color is a black or a light theme, and finally changes the font color in the custom notification according to the returned theme color.

step

Code is readable and directly source code.Copy since then Slightly different according to the actual project.

public boolean isDarkNotificationTheme() {
    return !isSimilarColor(Color.BLACK,getNotificationColor(musicService.getApplicationContext()));
}


public static int getNotificationColor(Context context) {
    NotificationCompat.Builder builder=new NotificationCompat.Builder(context);
    Notification notification=builder.build();
    int layoutId=notification.contentView.getLayoutId();
    ViewGroup viewGroup= (ViewGroup) LayoutInflater.from(context).inflate(layoutId, null, false);
    if (viewGroup.findViewById(android.R.id.title)!=null) {
        return ((TextView) viewGroup.findViewById(android.R.id.title)).getCurrentTextColor();
    }
    return findColor(viewGroup);
}


private boolean isSimilarColor(int baseColor, int color) {
    int simpleBaseColor=baseColor|0xff000000;
    int simpleColor=color|0xff000000;
    int baseRed=Color.red(simpleBaseColor)-Color.red(simpleColor);
    int baseGreen=Color.green(simpleBaseColor)-Color.green(simpleColor);
    int baseBlue=Color.blue(simpleBaseColor)-Color.blue(simpleColor);
    double value=Math.sqrt(baseRed*baseRed+baseGreen*baseGreen+baseBlue*baseBlue);
    if (value<180.0) {
        return true;
    }
    return false;
}


private static int findColor(ViewGroup viewGroupSource) {
    int color=Color.TRANSPARENT;
    LinkedList<ViewGroup> viewGroups=new LinkedList<>();
    viewGroups.add(viewGroupSource);
    while (viewGroups.size()>0) {
        ViewGroup viewGroup1=viewGroups.getFirst();
        for (int i = 0; i < viewGroup1.getChildCount(); i++) {
            if (viewGroup1.getChildAt(i) instanceof ViewGroup) {
                viewGroups.add((ViewGroup) viewGroup1.getChildAt(i));
            }
            else if (viewGroup1.getChildAt(i) instanceof TextView) {
                if (((TextView) viewGroup1.getChildAt(i)).getCurrentTextColor()!=-1) {
                    color=((TextView) viewGroup1.getChildAt(i)).getCurrentTextColor();
                }
            }
        }
        viewGroups.remove(viewGroup1);
    }
    return color;
}

Last Passed

contentView.setInt(R.id.share_content, "setTextColor", NotificationUtils.isDarkNotificationTheme()==true?Color.WHITE:Color.BLACK);

Implement the function of color replacement.

Advantages and disadvantages

Advantages: You can customize the font color of Title and Introduction in notifications;
Disadvantage: It seems that the buttons in the notification still cannot be replaced.

In addition, I try to change the color and icon of the font in the notification by returning the specific result of isDarkNotificationTheme():

private View view;
private TextView notificationTitleTextView;
private TextView notificationSubtitleTextView;
private ImageView notificationPlayorpauseImageView;

View view = LayoutInflater.from(MusicPlayer.this).inflate(R.layout.music_notification, null);
notificationTitleTextView = (TextView) view.findViewById(R.id.notification_title_textView);
notificationsubTitleTextView = (TextView) view.findViewById(R.id.notification_subtitle_textView);
notificationPlayorpauseImageView = (ImageView) view.findViewById(R.id.notification_subtitle_textView);

if(isDarkNotificationTheme()){
    notificationTitleTextView.setTextColor(getResources().getColor(R.color.black));
    notificationsubtitleTextView.setTextColor(getResources().getColor(R.color.gray));
    notificationPlayorpauseImageView.setImageResource(R.mipmap.playOrPauseImageView);
}else{
//As above, replace with different colors/icons
}

However, it was found that the notification did not work, that is, this method is not applicable to notifications.

Option 3

The third scenario has two parts. The first is a small change to the first one to meet the requirements of adapting regardless of the Android version, but it does not solve the problem of not replacing icons.Second, it combines scheme one and scheme two to achieve the final text color/icon changes with the change of background color after the theme change of the mobile phone.

Mode 1:

Watch out for solutions 1 that are higher than Android version 5.0: although

"@android:style/TextAppearance.Material.Notification.Line2"

The minimum required version is API 21, but

"@android:style/TextAppearance.Material.Notification.Title"

The minimum required version is API 9 only. Considering that almost all Android phones on the market now have higher APIs than API 9, it can be set in Title's <TextView>

android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"

Set in <TextView>of Introduction

android:textAppearance="@style/TextAppearance.StatusBar.EventContent"

This enables Title and Introduction to have different gray-scale colors (Title is black/white, Introduction is gray to varying degrees) while maintaining high contrast between Title and Introduction.

Improvement:

Advantage: Easy and convenient; custom notification font color immediately responds to change after changing dark/light theme.
Disadvantage: Text color cannot be customized; icon color cannot be changed.

Mode 2

1) As scheme one has the characteristics of simple and fast response to text color when background changes, mode one is used in the font color of notification;
2) Using Scheme 2, we can know if the current theme is dark or light, and then use different color icons according to the theme color.

Step One

Add a line to the <TextView>that represents Title in the layout file for the notification:

...
    <TextView>
        ...
        android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"
        ...
    </TextView>

Add a line to the <TextView>that describes the Introduction in the layout file for the notification:

...
    <TextView>
        ...
        android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
        ...
    </TextView>

Step 2

First, use Scenario 2 to get if the current theme color is dark or light:

public boolean isDarkNotificationTheme() {
    return !isSimilarColor(Color.BLACK,getNotificationColor(musicService.getApplicationContext()));
}


public static int getNotificationColor(Context context) {
    NotificationCompat.Builder builder=new NotificationCompat.Builder(context);
    notification=builder.build();
    int layoutId=notification.contentView.getLayoutId();
    ViewGroup viewGroup= (ViewGroup) LayoutInflater.from(context).inflate(layoutId, null, false);
    if (viewGroup.findViewById(android.R.id.title)!=null) {
        return ((TextView) viewGroup.findViewById(android.R.id.title)).getCurrentTextColor();
    }
    return findColor(viewGroup);
}


private boolean isSimilarColor(int baseColor, int color) {
    int simpleBaseColor=baseColor|0xff000000;
    int simpleColor=color|0xff000000;
    int baseRed=Color.red(simpleBaseColor)-Color.red(simpleColor);
    int baseGreen=Color.green(simpleBaseColor)-Color.green(simpleColor);
    int baseBlue=Color.blue(simpleBaseColor)-Color.blue(simpleColor);
    double value=Math.sqrt(baseRed*baseRed+baseGreen*baseGreen+baseBlue*baseBlue);
    if (value<180.0) {
        return true;
    }
    return false;
}


private static int findColor(ViewGroup viewGroupSource) {
    int color=Color.TRANSPARENT;
    LinkedList<ViewGroup> viewGroups=new LinkedList<>();
    viewGroups.add(viewGroupSource);
    while (viewGroups.size()>0) {
        ViewGroup viewGroup1=viewGroups.getFirst();
        for (int i = 0; i < viewGroup1.getChildCount(); i++) {
            if (viewGroup1.getChildAt(i) instanceof ViewGroup) {
                viewGroups.add((ViewGroup) viewGroup1.getChildAt(i));
            }
            else if (viewGroup1.getChildAt(i) instanceof TextView) {
                if (((TextView) viewGroup1.getChildAt(i)).getCurrentTextColor()!=-1) {
                    color=((TextView) viewGroup1.getChildAt(i)).getCurrentTextColor();
                }
            }
        }
        viewGroups.remove(viewGroup1);
    }
    return color;
}

The function that replaces the icon in the notification is then implemented, calling Android's own method setImageViewResource to update the text and icon in the notification:

public void setNotificationColor(){
    if(isDarkNotificationTheme()){
        setImageViewResource(R.id.notification_play_pause, R.mipmap.ic_audio_playing_night);
        setImageViewResource(R.id.notification_img_next, R.mipmap.ic_audio_next_night);
    }else {
        setImageViewResource(R.id.notification_play_pause, R.mipmap.ic_audio_playing);
        setImageViewResource(R.id.notification_img_next, R.mipmap.ic_audio_next);
    }
    refreshView();
}

// private Notification notification builder.build();
// public static NotificationManager notificationManager = (NotificationManager)service.getSystemService(Context.NOTIFICATION_SERVICE);
private void refreshView(){
    if(notification != null){
        notificationManager.notify(NOTIFICATION_ID, notification);
}

That's it.If you want to define the font color for Title and Introduction in the notification yourself, add it in the if statement of the setNotificationColor() method

setTextColor(R.id.notification_title_textview, getResources().getColor(R.color.title_color));
setTextColor(R.id.notification_subtitle_textview, getResources().getColor(R.color.title_color));

The final effect is the top notification in the diagram, which shows the effect under dark theme and light theme respectively:

Note: R.mipmap.xxx is an icon added by itself in the android/src/main/res/mipmap folder in the project; R.color.xxxx is a self-defined color in the android/src/main/res/values/color.xml in the project.

Topics: Android less xml Mobile