Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73448836 authored by Andreas Miko's avatar Andreas Miko
Browse files

Make the border of PreviewIcons transparent

The border had a solid color before. This works for the Gallery example
but we have transparent and blured backgrounds in Notifications now.

The border was too thin before, increased to 2.5.dp

Bug: b/418022243
Test: Screenshot test
Flag: com.android.systemui.notification_bundle_ui
Change-Id: Ic59582be0dda7e4562c11df9e501db2525240546
parent b722564c
Loading
Loading
Loading
Loading
+67 −1
Original line number Diff line number Diff line
@@ -20,25 +20,38 @@ import android.content.Context
import android.graphics.drawable.Drawable
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.constrainHeight
import androidx.compose.ui.unit.constrainWidth
import androidx.compose.ui.unit.dp
@@ -207,20 +220,73 @@ private fun ContentScope.BundlePreviewIcons(
) {
    check(previewDrawables.isNotEmpty())
    val iconSize = 32.dp
    HalfOverlappingReversedRow(modifier = modifier) {

    val borderWidth = 2.5.dp
    HalfOverlappingReversedRow(
        modifier =
            modifier.graphicsLayer {
                // This is needed for rendering transparent PreviewIcon border
                compositingStrategy = CompositingStrategy.Offscreen
            }
    ) {
        PreviewIcon(
            drawable = previewDrawables[0],
            modifier = Modifier.element(BundleHeader.Elements.PreviewIcon1).size(iconSize),
            borderWidth = borderWidth,
        )
        if (previewDrawables.size < 2) return@HalfOverlappingReversedRow
        PreviewIcon(
            drawable = previewDrawables[1],
            modifier = Modifier.element(BundleHeader.Elements.PreviewIcon2).size(iconSize),
            borderWidth = borderWidth,
        )
        if (previewDrawables.size < 3) return@HalfOverlappingReversedRow
        PreviewIcon(
            drawable = previewDrawables[2],
            modifier = Modifier.element(BundleHeader.Elements.PreviewIcon3).size(iconSize),
            borderWidth = borderWidth,
        )
    }
}

/** The Icon used to display a preview of contained child notifications in a Bundle. */
@Composable
private fun PreviewIcon(drawable: Drawable, modifier: Modifier = Modifier, borderWidth: Dp) {
    val strokeWidthPx = with(LocalDensity.current) { borderWidth.toPx() }
    val stroke = remember(borderWidth) { Stroke(width = strokeWidthPx) }

    Box(
        modifier =
            modifier.drawWithContent {
                // Draw the original content of the inner Box
                drawContent()

                // Draw a circle with BlendMode.Clear to 'erase' pixels for the stroke.
                // This will punch a hole in *this* icon's local offscreen buffer, allowing the
                // background of the containing Composable (which needs to have a global
                // offscreen layer) to show through.
                drawCircle(
                    color = Color.Black, // Color doesn't matter for BlendMode.Clear
                    // Calculate the radius for the clearing circle.
                    // It should be the full size.minDimension / 2 PLUS half the stroke width.
                    // This pushes the *center* of the stroke outward, so the *inner* edge of the
                    // stroke aligns with the existing content boundary.
                    radius = (size.minDimension / 2f) + (strokeWidthPx / 2f),
                    center = center,
                    style = stroke,
                    blendMode = BlendMode.Clear,
                )
            }
    ) {
        val surfaceColor = notificationElementSurfaceColor()
        Image(
            painter = rememberDrawablePainter(drawable),
            contentDescription = null,
            modifier =
                Modifier.fillMaxSize()
                    .clip(CircleShape)
                    .background(color = surfaceColor, shape = CircleShape),
            contentScale = ContentScale.Fit,
        )
    }
}
+1 −25
Original line number Diff line number Diff line
@@ -16,11 +16,9 @@

package com.android.systemui.notifications.ui.composable.row

import android.graphics.drawable.Drawable
import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
@@ -39,7 +37,6 @@ import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.graphics.Color
@@ -55,7 +52,6 @@ import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.LowestZIndexContentPicker
import com.android.compose.animation.scene.ValueKey
import com.android.compose.animation.scene.animateElementFloatAsState
import com.android.compose.ui.graphics.painter.rememberDrawablePainter

object NotificationRowPrimitives {
    object Elements {
@@ -85,26 +81,6 @@ fun BundleIcon(@DrawableRes drawable: Int?, modifier: Modifier = Modifier) {
    }
}

/** The Icon used to display a preview of contained child notifications in a Bundle. */
@Composable
fun PreviewIcon(drawable: Drawable, modifier: Modifier = Modifier) {
    val surfaceColor = notificationElementSurfaceColor()
    Box(
        modifier =
            modifier
                .background(color = surfaceColor, shape = CircleShape)
                .border(0.5.dp, surfaceColor, CircleShape)
    ) {
        val painter = rememberDrawablePainter(drawable)
        Image(
            painter = painter,
            contentDescription = null,
            modifier = Modifier.fillMaxSize().clip(CircleShape),
            contentScale = ContentScale.Fit,
        )
    }
}

/** The ExpansionControl of any expandable notification row, containing a Chevron. */
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
@@ -156,7 +132,7 @@ private fun ContentScope.PillBackground(modifier: Modifier = Modifier) {

@Composable
@ReadOnlyComposable
private fun notificationElementSurfaceColor(): Color {
fun notificationElementSurfaceColor(): Color {
    return if (isSystemInDarkTheme()) {
        Color.White.copy(alpha = 0.15f)
    } else {