最近完成了一個需要自定義RemoteViews的Notification的需求,期間遇到了不少關於顏色適配的問題,在此做一下總結
在Notification上使用我們自定義的RemoteViews時,通知欄的背景色、標題文字色跟內容文字色是我們需要注意的三種顏色,如果設置不當,可能會導致我們自定義的通知欄的通知看不清楚
一般而言,我們可以通過:
不設置自定義view的背景色,標題與內容設置系統的style來解決這個問題:
SDK21以下:
// 標題樣式
android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent.Title"
// 內容樣式
android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent"
SDK21以及以上:
// 標題樣式
android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"
// 內容樣式
android:textAppearance="@android:style/TextAppearance.Material.Notification.Info"
但是實際測試中發現,在某些國產機型上會出現設置錯誤的標題跟內容文字顏色的問題
因此,這邊通過先構造一個系統的Notification,再取出其中對應顏色的方法,寫了一個獲取通知欄顏色的工具類:
/**
* Created by superxlcr on 2018/2/4.
*
* 獲取通知欄顏色工具類
*/
public class NotificationUtils {
//<editor-fold desc="property">
private static final String TITLE = "title";
private static final String CONTENT = "content";
private static final float COLOR_THRESHOLD = 180f;
private static int backgroundColor = Color.TRANSPARENT;
private static int titleColor = Color.WHITE;
private static int contentColor = Color.WHITE;
private static boolean checkDeviceColors = false;
//</editor-fold>
//<editor-fold desc="public">
/**
* 獲取Notification背景色
*
* @param context 上下文
* @return 背景色,獲取失敗時默認爲 透明色
*/
public static int getBackgroundColor(Context context) {
checkDeviceColors(context);
return backgroundColor;
}
/**
* 獲取Notification標題色
*
* @param context 上下文
* @return 標題色,獲取失敗時默認爲 白色
*/
public static int getTitleColor(Context context) {
checkDeviceColors(context);
return titleColor;
}
/**
* 獲取Notification內容色
*
* @param context 上下文
* @return 內容色,獲取失敗時默認爲 白色
*/
public static int getContentColor(Context context) {
checkDeviceColors(context);
return contentColor;
}
//</editor-fold>
//<editor-fold desc="private">
private NotificationUtils() {
}
private static void checkDeviceColors(Context context) {
if (checkDeviceColors || context == null) {
return;
}
checkDeviceColors = true;
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
Notification notification = builder.setContentTitle(TITLE).setContentText(CONTENT).build();
View notificationView = notification.contentView.apply(context, new LinearLayout(context));
if (notificationView instanceof ViewGroup) {
TextView title = findTextViewByText((ViewGroup) notificationView, TITLE);
if (title != null) {
titleColor = title.getCurrentTextColor();
// 黑色標題使用白色背景,其他標題使用透明背景
if (isSimilarColor(Color.BLACK, titleColor)) {
backgroundColor = Color.WHITE;
} else {
backgroundColor = Color.TRANSPARENT;
}
}
TextView content = findTextViewByText((ViewGroup) notificationView, CONTENT);
if (content != null) {
contentColor = content.getCurrentTextColor();
}
}
}
private static TextView findTextViewByText(ViewGroup viewGroup, String text) {
if (viewGroup == null) {
return null;
}
int size = viewGroup.getChildCount();
for (int i = 0; i < size; i++) {
View view = viewGroup.getChildAt(i);
if (view instanceof TextView) {
TextView textView = (TextView) view;
if (TextUtils.equals(textView.getText(), text)) {
return textView;
}
} else if (view instanceof ViewGroup) {
TextView textView = findTextViewByText((ViewGroup) view, text);
if (textView != null) {
return null;
}
}
}
return null;
}
private static 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);
return value < COLOR_THRESHOLD;
}
//</editor-fold>
}
其中,由於Android的通知欄底色一般爲白色、黑色或者透明,因此在工具類中根據標題文字色的顏色,爲背景對應設置白色或透明