app/src/main/java/fr/neamar/kiss/utils/DrawableUtils.java
/**
     * Handle adaptive icons for compatible devices
     */
Handle adaptive icons for compatible devices
Handle adaptive icons for compatible devices
@SuppressLint("NewApi")
    public static Drawable applyIconMaskShape(Context ctx, Drawable icon, int shape, boolean fitInside, @ColorInt int backgroundColor) {
        if (shape == SHAPE_SYSTEM)
            return icon;
        if (shape == SHAPE_TEARDROP_RND)
            shape = SHAPE_TEARDROP_BR + (icon.hashCode() % 4);
        Bitmap outputBitmap;
        Canvas outputCanvas;
        final Paint outputPaint = PAINT;
        outputPaint.reset();
        outputPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        if (isAdaptiveIconDrawable(icon)) {
            AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) icon;
            Drawable bgDrawable = adaptiveIcon.getBackground();
            Drawable fgDrawable = adaptiveIcon.getForeground();
            int layerSize = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 108f, ctx.getResources().getDisplayMetrics()));
            int iconSize = Math.round(layerSize / (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction()));
            int layerOffset = (layerSize - iconSize) / 2;
            Bitmap iconBitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
            Canvas iconCanvas = new Canvas(iconBitmap);
            bgDrawable.setBounds(-layerOffset, -layerOffset, iconSize + layerOffset, iconSize + layerOffset);
            bgDrawable.draw(iconCanvas);
            fgDrawable.setBounds(-layerOffset, -layerOffset, iconSize + layerOffset, iconSize + layerOffset);
            fgDrawable.draw(iconCanvas);
            outputBitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
            outputCanvas = new Canvas(outputBitmap);
            outputPaint.setShader(new BitmapShader(iconBitmap, TileMode.CLAMP, TileMode.CLAMP));
            setIconShape(outputCanvas, outputPaint, shape);
            outputPaint.setShader(null);
        }
        else if (icon != null) {
            int iconSize;
            int iconOffset = 0;
            if (fitInside) {
                float marginPercent = getScaleToFit(shape);
                int iconHeight = icon.getIntrinsicHeight();
                if (iconHeight <= 0)
                    iconHeight = ctx.getResources().getDimensionPixelSize(R.dimen.result_icon_size);
                iconSize = Math.round((1f + 2f * marginPercent) * iconHeight);
                iconOffset = Math.round(marginPercent * iconHeight);
            } else {
                iconSize = 2 * ctx.getResources().getDimensionPixelSize(R.dimen.result_icon_size);
            }
            outputBitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
            outputCanvas = new Canvas(outputBitmap);
            outputPaint.setColor(backgroundColor);
            int bottomRightCorner = iconSize - iconOffset;
            icon.setBounds(iconOffset, iconOffset, bottomRightCorner, bottomRightCorner);
            setIconShape(outputCanvas, outputPaint, shape);
            icon.draw(outputCanvas);
        } else {
            int iconSize = ctx.getResources().getDimensionPixelSize(R.dimen.result_icon_size);
            outputBitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
            outputCanvas = new Canvas(outputBitmap);
            outputPaint.setColor(0xFF000000);
            setIconShape(outputCanvas, outputPaint, shape);
        }
        return new BitmapDrawable(ctx.getResources(), outputBitmap);
    }
@ SuppressLint ( "NewApi" ) public static Drawable applyIconMaskShape ( Context ctx , Drawable icon , int shape , boolean fitInside , @ ColorInt int backgroundColor ) { if ( shape == SHAPE_SYSTEM ) return icon ; if ( shape == SHAPE_TEARDROP_RND ) shape = SHAPE_TEARDROP_BR + ( icon . hashCode ( ) % 4 ) ; Bitmap outputBitmap ; Canvas outputCanvas ; final Paint outputPaint = PAINT ; outputPaint . reset ( ) ; outputPaint . setFlags ( Paint . ANTI_ALIAS_FLAG ) ; if ( isAdaptiveIconDrawable ( icon ) ) { AdaptiveIconDrawable adaptiveIcon = ( AdaptiveIconDrawable ) icon ; Drawable bgDrawable = adaptiveIcon . getBackground ( ) ; Drawable fgDrawable = adaptiveIcon . getForeground ( ) ; int layerSize = Math . round ( TypedValue . applyDimension ( TypedValue . COMPLEX_UNIT_DIP , 108f , ctx . getResources ( ) . getDisplayMetrics ( ) ) ) ; int iconSize = Math . round ( layerSize / ( 1 + 2 * AdaptiveIconDrawable . getExtraInsetFraction ( ) ) ) ; int layerOffset = ( layerSize - iconSize ) / 2 ; Bitmap iconBitmap = Bitmap . createBitmap ( iconSize , iconSize , Bitmap . Config . ARGB_8888 ) ; Canvas iconCanvas = new Canvas ( iconBitmap ) ; bgDrawable . setBounds ( - layerOffset , - layerOffset , iconSize + layerOffset , iconSize + layerOffset ) ; bgDrawable . draw ( iconCanvas ) ; fgDrawable . setBounds ( - layerOffset , - layerOffset , iconSize + layerOffset , iconSize + layerOffset ) ; fgDrawable . draw ( iconCanvas ) ; outputBitmap = Bitmap . createBitmap ( iconSize , iconSize , Bitmap . Config . ARGB_8888 ) ; outputCanvas = new Canvas ( outputBitmap ) ; outputPaint . setShader ( new BitmapShader ( iconBitmap , TileMode . CLAMP , TileMode . CLAMP ) ) ; setIconShape ( outputCanvas , outputPaint , shape ) ; outputPaint . setShader ( null ) ; } else if ( icon != null ) { int iconSize ; int iconOffset = 0 ; if ( fitInside ) { float marginPercent = getScaleToFit ( shape ) ; int iconHeight = icon . getIntrinsicHeight ( ) ; if ( iconHeight <= 0 ) iconHeight = ctx . getResources ( ) . getDimensionPixelSize ( R . dimen . result_icon_size ) ; iconSize = Math . round ( ( 1f + 2f * marginPercent ) * iconHeight ) ; iconOffset = Math . round ( marginPercent * iconHeight ) ; } else { iconSize = 2 * ctx . getResources ( ) . getDimensionPixelSize ( R . dimen . result_icon_size ) ; } outputBitmap = Bitmap . createBitmap ( iconSize , iconSize , Bitmap . Config . ARGB_8888 ) ; outputCanvas = new Canvas ( outputBitmap ) ; outputPaint . setColor ( backgroundColor ) ; int bottomRightCorner = iconSize - iconOffset ; icon . setBounds ( iconOffset , iconOffset , bottomRightCorner , bottomRightCorner ) ; setIconShape ( outputCanvas , outputPaint , shape ) ; icon . draw ( outputCanvas ) ; } else { int iconSize = ctx . getResources ( ) . getDimensionPixelSize ( R . dimen . result_icon_size ) ; outputBitmap = Bitmap . createBitmap ( iconSize , iconSize , Bitmap . Config . ARGB_8888 ) ; outputCanvas = new Canvas ( outputBitmap ) ; outputPaint . setColor ( 0xFF000000 ) ; setIconShape ( outputCanvas , outputPaint , shape ) ; } return new BitmapDrawable ( ctx . getResources ( ) , outputBitmap ) ; }
Handle adaptive icons for compatible devices
Handle adaptive icons for compatible devices
// Create a bitmap of the icon to use it as the shader of the outputBitmap // Stretch adaptive layers because they are 108dp and the icon size is 48dp // If icon is not adaptive, put it in a white canvas to make it have a unified shape // Shrink icon fit inside the shape // we don't have antialiasing when clipping so we make the icon bigger and let the View downscale // Shrink icon so that it fits the shape