NotificationCompat 中的 BigTextStyle 导致图形错误

BigTextStyle in NotificationCompat cause graphical bug

我有一个通知,支持私有和 public 版本。私有版本显示为 bigTextStyle。两个版本的图标都生成为 LayerDrawable,然后将其转换为位图。这适用于所有设备。除了在地狱中锻造的华为 Ascent Mate 7。 (Android 4.4.2, EMUI 3.0)

在未展开的版本中,它看起来应该如此。圆圈,适合图标。

但在放大版中,它看起来就像是从图标的缩放版中剪下来的。

我做的图标如下:

        Drawable background = ContextCompat.getDrawable(this, R.drawable.shape_notification_circle);
        if (background != null) {
            PorterDuffColorFilter filter = new PorterDuffColorFilter(ThemeManager.getInstance().getTheme()
                    .getColorMainDark(), PorterDuff.Mode.SRC_ATOP);
            background.setColorFilter(filter);
        }

        Drawable[] layers = {background, ContextCompat.getDrawable(this, icon)};
        //icon is an int, containing the resource id
        LayerDrawable layerDrawable = new LayerDrawable(layers);

        int padding = dpToPx(24);

        layerDrawable.setLayerInset(1, padding, padding, padding, padding);

        Bitmap iconBitmap = drawableToBitmap(layerDrawable);

方法 drawableToBitmap:

public static Bitmap drawableToBitmap(Drawable drawable) {
        Bitmap bitmap;

        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            if (bitmapDrawable.getBitmap() != null) {
                return bitmapDrawable.getBitmap();
            }
        }

        if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
            bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of
            // 1x1 pixel
        } else {
            bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config
                    .ARGB_8888);
        }

        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);
        return bitmap;
    }

shape_notification_circle

的布局
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="oval">

    <solid android:color="#666666"/>

    <size
        android:width="48dp"
        android:height="48dp"/>
</shape>

可绘制的图标:

<?xml version="1.0" encoding="UTF-8"?>
<vector android:height="48dp"
        android:viewportHeight="1000.0"
        android:viewportWidth="1000.0"
        android:width="48dp"
        xmlns:android="http://schemas.android.com/apk/res/android">
    <path
        android:fillColor="#FFFFFF"
        android:pathData="M500,609.8l-75.20001,-72.79999l-299.69998,252.79999l749.80005,0l-299.7,-252.79999z"/>
    <path
        android:fillColor="#FFFFFF"
        android:pathData="M122.6,210.2l377.4,365l377.40002,-365z"/>
    <path
        android:fillColor="#FFFFFF"
        android:pathData="M406.3,519.7l-300.9,-292.2l0,546.3z"/>
    <path
        android:fillColor="#FFFFFF"
        android:pathData="M894.6,773.8l0,-546.3l-300.89996,292.2z"/>
</vector>

最后,创建通知。 (notificationBuilder和notificationBuilderPublic以前是不同的,现在一样了,除了bigTextStyle不同)

// @formatter:off
            NotificationCompat.Builder notificationBuilderPublic = new NotificationCompat.Builder(this)
                    .setLargeIcon(iconBitmap)
                    .setSmallIcon(R.drawable.ic_notification_launcher)
                    .setColor(ThemeManager.getInstance().getTheme().getColorAccent())
                    .setDefaults(Notification.DEFAULT_ALL)
                    .setContentTitle(getString(R.string.app_name))
                    .setContentText(title)
                    .setAutoCancel(true)
                    .setContentIntent(pendingIntent)
                    .setCategory(category)
                    .setPriority(priority)
                    .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                    ;

            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                    .setLargeIcon(iconBitmap)
                    .setSmallIcon(R.drawable.ic_notification_launcher)
                    .setColor(ThemeManager.getInstance().getTheme().getColorAccent())
                    .setDefaults(Notification.DEFAULT_ALL)
                    .setContentTitle(getString(R.string.app_name))
                    .setContentText(title)
                    .setAutoCancel(true)
                    .setContentIntent(pendingIntent)
                    .setCategory(category)
                    .setPriority(priority)
                    .setVisibility(visibility)
                    ;
            // @formatter:on

            notificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(text)
                    .setBigContentTitle(getString(R.string.app_name)).setSummaryText(extraSummary));


            notificationBuilder.setPublicVersion(notificationBuilderPublic.build());


        notificationManager.notify(pushId + "|" + ownermoduleid + "|" + fid, type.getId(), notificationBuilder.build());

我做错了什么?

编辑:添加布局和图标XML

最后我找到了...好吧,我不会称之为解决方案...一种变通方法。看起来,在 LayerDrawable 的图层上设置 insets 会导致图像变大。如果某些设备太大,它们似乎会裁剪图像而不是适合它们。

这导致我在将 iconBitmap 设置为 LargeIcon 之前调整它的大小。

Bitmap iconBitmap = scaleDown(drawableToBitmap(layerDrawable), dpToPx(48), true);

和缩放函数

 public Bitmap scaleDown(Bitmap source, int size, boolean filter) {
            return Bitmap.createScaledBitmap(source, size, size, filter);
        }

这仍然不能完美无缺。展开通知时,图像稍微小了一点,但这对我来说没问题。还是比裁剪的好。

我还是不知道,为什么只有在展开视图时才会出现这种情况。也许华为的人实现了不同于普通样式的 BigTextStyle。或者也许这只是一些黑魔法...

如果有人提出更好的解决方案,我会接受。