android系统一直显示通知栏_android系统适配通知栏背景的一种方案

android系统适配通知栏背景的一种方案

现状:

目前android碎片化严重,很多厂商会针对android系统底层进行改造,通知栏也不例外,类似小米手机或者华为的一些手机,通知栏就不是原生android的,有些通知栏的背景是黑色,有些通知栏的背景是白色,所以在应用中需要自定义通知栏的时候,很难去适配机器自身通知栏的样式,目前很多应用在实现自定义通知栏的时候,为了适配所有机型,通常会在自定义通知栏的时候加一层背景,例如下面的360:

4df93a19d88cc7a0ed36ed2734cd06dc.png

如何进行对各种手机适配呢

适配的方式大概有两种,一种简单粗暴:为自定义通知设置固定的背景(上图中的360卫士就这么干的),比如黑色。那么内容自然就是白色或近似白色。这样,在所有的手机上都能正常显示,不会出现在黑色背景通知栏上显示良好,到了白色背景通知栏上就几乎啥也看不见。使用这种方案的应用太多了。我个人很不推崇这种方式,这样会使得自定义通知在将近一半的手机上显示得很突兀,和系统的通知栏不够沉浸,影响整体美观。另一种方案就稍微合理一些:通过读取系统的通知栏样式文件,获取到title和content的颜色,进而将这个颜色设置到自定义通知上。读取通知栏样式文件本身有兼容性问题,不同Android版本的样式文件有变,具体可参考这篇博客 通知栏设置系统字体颜色 ,这种方式也不是在所有手机上生效,实际测试发现,还是有小部分机型没法读取或是读取到的是错误的。拿到title和content的颜色后,还可以通过算法(后面细说)判断这个颜色是近似白色还是近似黑色,进而能判断出通知栏的背景是近似黑色还是近似白色,这样就能根据不同的通知栏背景加载不同的自定义通知布局。进而做到良好的适配。

代码实现

/**

* 通知栏的帮助类,提供查询手机是否禁止通知栏,判断通知栏背景颜色

* Created by dengqu on 2016/12/12.

*/

public class NotificationsUtils {

private final static String TAG = NotificationsUtils.class.getSimpleName();

private static final String CHECK_OP_NO_THROW = "checkOpNoThrow";

private static final String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";

private static final double COLOR_THRESHOLD = 180.0;

private static int titleColor;

/**

* 判断应用通知栏是否开启权限

*

* @param context

* @return

*/

public static boolean isNotificationEnabled(Context context) {

try {

if (AndroidConfig.getAndroidVersion() >= Build.VERSION_CODES.KITKAT) {

AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);

ApplicationInfo appInfo = context.getApplicationInfo();

String pkg = context.getApplicationContext().getPackageName();

int uid = appInfo.uid;

Class appOpsClass = null;

appOpsClass = Class.forName(AppOpsManager.class.getName());

Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE, String.class);

Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);

int value = (int) opPostNotificationValue.get(Integer.class);

return ((int) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) == AppOpsManager.MODE_ALLOWED);

}

} catch (Exception e) {

XLLog.e(TAG, e);

}

return true;

}

/**

* 判断通知栏背景颜色,现在手机通知栏大部分不是白色就是黑色背景

*

* @param context

* @return

*/

public static boolean isDarkNotiFicationBar(Context context) {

return !isColorSimilar(Color.BLACK, getNotificationColor(context));

}

private static int getNotificationColor(Context context) {

if (context instanceof AppCompatActivity) {

return getNotificationColorCompat(context);

} else {

return getNotificationColorInternal(context);

}

}

private static boolean isColorSimilar(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 < COLOR_THRESHOLD) {

return true;

}

return false;

}

private static int getNotificationColorInternal(Context context) {

final String DUMMY_TITLE = "DUMMY_TITLE";

NotificationCompat.Builder builder = new NotificationCompat.Builder(context);

builder.setContentText(DUMMY_TITLE);

Notification notification = builder.build();

ViewGroup notificationRoot = (ViewGroup) notification.contentView.apply(context, new FrameLayout(context));

final TextView titleView = (TextView) notificationRoot.findViewById(android.R.id.title);

if (titleView == null) {

iteratoryView(notificationRoot, new Filter() {

@Override

public void filter(View view) {

if (view instanceof TextView) {

TextView textView = (TextView) view;

if (DUMMY_TITLE.equals(textView.getText().toString())) {

titleColor = textView.getCurrentTextColor();

}

}

}

});

return titleColor;

} else {

return titleView.getCurrentTextColor();

}

}

private static int getNotificationColorCompat(Context context) {

NotificationCompat.Builder builder = new NotificationCompat.Builder(context);

Notification notification = builder.build();

int layoutId = notification.contentView.getLayoutId();

ViewGroup notificationRoot = (ViewGroup) LayoutInflater.from(context).inflate(layoutId, null);

final TextView titleView = (TextView) notificationRoot.findViewById(android.R.id.title);

if (titleView == null) {

final List textViews = new ArrayList<>();

iteratoryView(notificationRoot, new Filter() {

@Override

public void filter(View view) {

textViews.add((TextView) view);

}

});

float minTextSize = Integer.MIN_VALUE;

int index = 0;

for (int i = 0, j = textViews.size(); i < j; i++) {

float currentSize = textViews.get(i).getTextSize();

if (currentSize > minTextSize) {

minTextSize = currentSize;

index = i;

}

}

return textViews.get(index).getCurrentTextColor();

} else {

return titleView.getCurrentTextColor();

}

}

private static void iteratoryView(View view, Filter filter) {

if (view == null || filter == null) {

return;

}

filter.filter(view);

if (view instanceof ViewGroup) {

ViewGroup container = (ViewGroup) view;

for (int i = 0, j = container.getChildCount(); i < j; i++) {

View child = container.getChildAt(i);

iteratoryView(child, filter);

}

}

}

private interface Filter {

void filter(View view);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值