Skip to content

Commit

Permalink
Merge pull request #2220 from HedvigInsurance/fix/android-8-not-rende…
Browse files Browse the repository at this point in the history
…ring-clipped-content

Fix Android <= 8.1 not rendering clipped content properly
  • Loading branch information
StylianosGakis authored Sep 10, 2024
2 parents 183a102 + eb8d4b2 commit 3748641
Show file tree
Hide file tree
Showing 20 changed files with 155 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ private val buildConstantsModule = module {
override val isDebug: Boolean = BuildConfig.DEBUG
override val isProduction: Boolean =
BuildConfig.BUILD_TYPE == "release" && BuildConfig.APPLICATION_ID == "com.hedvig.app"
override val buildApiVersion: Int = Build.VERSION.SDK_INT
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.hedvig.android.app.urihandler.DeepLinkFirstUriHandler
import com.hedvig.android.app.urihandler.SafeAndroidUriHandler
import com.hedvig.android.auth.AuthStatus
import com.hedvig.android.auth.AuthTokenService
import com.hedvig.android.compose.ui.UseSimplerShapesForOldAndroidVersions
import com.hedvig.android.core.appreview.WaitUntilAppReviewDialogShouldBeOpenedUseCase
import com.hedvig.android.core.buildconstants.HedvigBuildConstants
import com.hedvig.android.core.demomode.DemoManager
Expand Down Expand Up @@ -99,7 +100,10 @@ internal fun HedvigApp(
navController = hedvigAppState.navController,
delegate = SafeAndroidUriHandler(LocalContext.current),
)
CompositionLocalProvider(LocalUriHandler provides deepLinkFirstUriHandler) {
CompositionLocalProvider(
LocalUriHandler provides deepLinkFirstUriHandler,
UseSimplerShapesForOldAndroidVersions provides (hedvigBuildConstants.buildApiVersion <= 27),
) {
HedvigAppUi(
hedvigAppState = hedvigAppState,
hedvigDeepLinkContainer = hedvigDeepLinkContainer,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.hedvig.android.compose.ui

import androidx.compose.runtime.staticCompositionLocalOf

/**
* https://issuetracker.google.com/issues/347031392
* In API versions 27 and lower, we default to a rounded corner shape instead of the more intricate shape since there
* is a bug with nothing rendering at all for all UI clipped with any generic shape.
*/
val UseSimplerShapesForOldAndroidVersions = staticCompositionLocalOf { false }
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,9 @@ interface HedvigBuildConstants {
* do sometimes want to know the difference.
*/
val isProduction: Boolean

/**
* The Android SDK version we are currently running on
*/
val buildApiVersion: Int
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ fun HedvigBottomSheet(
sheetState = sheetState,
tonalElevation = 0.dp,
shape = MaterialTheme.shapes.squircleLargeTop,
windowInsets = BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top),
contentWindowInsets = { BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top) },
) {
Column(
modifier = Modifier.verticalScroll(rememberScrollState()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ private fun Card(
shape = shape,
color = colors.containerColor(enabled = true),
contentColor = colors.contentColor(enabled = true),
tonalElevation = elevation.tonalElevation(enabled = true),
shadowElevation = elevation.shadowElevation(enabled = true, interactionSource = null).value,
border = border,
) {
Expand Down Expand Up @@ -141,7 +140,6 @@ private fun Card(
shape = shape,
color = colors.containerColor(enabled),
contentColor = colors.contentColor(enabled),
tonalElevation = elevation.tonalElevation(enabled),
shadowElevation = elevation.shadowElevation(enabled, interactionSource).value,
border = border,
interactionSource = interactionSource,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.graphics.Shape
import com.hedvig.android.compose.ui.UseSimplerShapesForOldAndroidVersions
import com.hedvig.android.core.designsystem.material3.fromToken

@Suppress("unused")
Expand All @@ -23,4 +24,4 @@ internal enum class HedvigShapeKeyTokens {
internal val HedvigShapeKeyTokens.value: Shape
@Composable
@ReadOnlyComposable
get() = MaterialTheme.shapes.fromToken(this)
get() = MaterialTheme.shapes.fromToken(this, UseSimplerShapesForOldAndroidVersions.current)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package com.hedvig.android.core.designsystem.material3

import androidx.annotation.FloatRange
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Shapes
Expand All @@ -23,6 +24,7 @@ import androidx.compose.ui.unit.dp
import androidx.graphics.shapes.CornerRounding
import androidx.graphics.shapes.RoundedPolygon
import androidx.graphics.shapes.toPath
import com.hedvig.android.compose.ui.UseSimplerShapesForOldAndroidVersions
import com.hedvig.android.core.designsystem.component.tokens.HedvigShapeKeyTokens

// Take shapes from existing theme setup
Expand Down Expand Up @@ -76,21 +78,38 @@ private val SquircleExtraSmall = FigmaShape(8.dp)
private val SquircleExtraSmallTop = FigmaShape(8.dp).top()
private val SquircleSmall = FigmaShape(10.dp)
private val SquircleMedium = FigmaShape(12.dp)
private val SquircleMediumTop = FigmaShape(12.dp).top()
private val SquircleLarge = FigmaShape(16.dp)
private val SquircleLargeTop = FigmaShape(16.dp).top()
private val SquircleExtraLarge = FigmaShape(24.dp)
private val SquircleExtraLargeTop = FigmaShape(24.dp).top()

val Shapes.squircleExtraSmall: Shape get() = SquircleExtraSmall
val Shapes.squircleExtraSmallTop: Shape get() = SquircleExtraSmallTop
val Shapes.squircleSmall: Shape get() = SquircleSmall
val Shapes.squircleMedium: Shape get() = SquircleMedium
val Shapes.squircleMediumTop: Shape get() = SquircleMediumTop
val Shapes.squircleLarge: Shape get() = SquircleLarge
val Shapes.squircleLargeTop: Shape get() = SquircleLargeTop
val Shapes.squircleExtraLarge: Shape get() = SquircleExtraLarge
val Shapes.squircleExtraLargeTop: Shape get() = SquircleExtraLargeTop
private val RoundedSquircleExtraSmall = RoundedCornerShape(8.dp)
private val RoundedSquircleExtraSmallTop = RoundedCornerShape(8.dp)
.copy(bottomStart = CornerSize(0), bottomEnd = CornerSize(0))
private val RoundedSquircleSmall = RoundedCornerShape(10.dp)
private val RoundedSquircleMedium = RoundedCornerShape(12.dp)
private val RoundedSquircleLarge = RoundedCornerShape(16.dp)
private val RoundedSquircleLargeTop = RoundedCornerShape(16.dp)
.copy(bottomStart = CornerSize(0), bottomEnd = CornerSize(0))
private val RoundedSquircleExtraLarge = RoundedCornerShape(24.dp)
private val RoundedSquircleExtraLargeTop = RoundedCornerShape(24.dp)
.copy(bottomStart = CornerSize(0), bottomEnd = CornerSize(0))

val Shapes.squircleExtraSmall: Shape
@Composable
get() = if (UseSimplerShapesForOldAndroidVersions.current) RoundedSquircleExtraSmall else SquircleExtraSmall
val Shapes.squircleSmall: Shape
@Composable
get() = if (UseSimplerShapesForOldAndroidVersions.current) RoundedSquircleSmall else SquircleSmall
val Shapes.squircleMedium: Shape
@Composable
get() = if (UseSimplerShapesForOldAndroidVersions.current) RoundedSquircleMedium else SquircleMedium
val Shapes.squircleLarge: Shape
@Composable
get() = if (UseSimplerShapesForOldAndroidVersions.current) RoundedSquircleLarge else SquircleLarge
val Shapes.squircleLargeTop: Shape
@Composable
get() = if (UseSimplerShapesForOldAndroidVersions.current) RoundedSquircleLargeTop else SquircleLargeTop

/**
* Turns the shape into one where only the top corners apply, by combining the path with a square path at the bottom.
Expand Down Expand Up @@ -120,24 +139,39 @@ private fun Shape.top(): Shape = object : Shape {
* tokens:
* ``MaterialTheme.shapes.fromToken(FabPrimarySmallTokens.ContainerShape)``
*/
internal fun Shapes.fromToken(value: HedvigShapeKeyTokens): Shape {
return when (value) {
HedvigShapeKeyTokens.CornerExtraLarge -> SquircleExtraLarge
HedvigShapeKeyTokens.CornerExtraLargeTop -> SquircleExtraLargeTop
HedvigShapeKeyTokens.CornerExtraSmall -> SquircleExtraSmall
HedvigShapeKeyTokens.CornerExtraSmallTop -> SquircleExtraSmallTop
HedvigShapeKeyTokens.CornerFull -> CircleShape
HedvigShapeKeyTokens.CornerLarge -> SquircleLarge
HedvigShapeKeyTokens.CornerLargeTop -> SquircleLargeTop
HedvigShapeKeyTokens.CornerMedium -> SquircleMedium
HedvigShapeKeyTokens.CornerNone -> RectangleShape
HedvigShapeKeyTokens.CornerSmall -> SquircleSmall
internal fun Shapes.fromToken(token: HedvigShapeKeyTokens, useSimplerShapes: Boolean): Shape {
return if (useSimplerShapes) {
when (token) {
HedvigShapeKeyTokens.CornerExtraLarge -> RoundedSquircleExtraLarge
HedvigShapeKeyTokens.CornerExtraLargeTop -> RoundedSquircleExtraLargeTop
HedvigShapeKeyTokens.CornerExtraSmall -> RoundedSquircleExtraSmall
HedvigShapeKeyTokens.CornerExtraSmallTop -> RoundedSquircleExtraSmallTop
HedvigShapeKeyTokens.CornerFull -> CircleShape
HedvigShapeKeyTokens.CornerLarge -> RoundedSquircleLarge
HedvigShapeKeyTokens.CornerLargeTop -> RoundedSquircleLargeTop
HedvigShapeKeyTokens.CornerMedium -> RoundedSquircleMedium
HedvigShapeKeyTokens.CornerNone -> RectangleShape
HedvigShapeKeyTokens.CornerSmall -> RoundedSquircleSmall
}
} else {
when (token) {
HedvigShapeKeyTokens.CornerExtraLarge -> SquircleExtraLarge
HedvigShapeKeyTokens.CornerExtraLargeTop -> SquircleExtraLargeTop
HedvigShapeKeyTokens.CornerExtraSmall -> SquircleExtraSmall
HedvigShapeKeyTokens.CornerExtraSmallTop -> SquircleExtraSmallTop
HedvigShapeKeyTokens.CornerFull -> CircleShape
HedvigShapeKeyTokens.CornerLarge -> SquircleLarge
HedvigShapeKeyTokens.CornerLargeTop -> SquircleLargeTop
HedvigShapeKeyTokens.CornerMedium -> SquircleMedium
HedvigShapeKeyTokens.CornerNone -> RectangleShape
HedvigShapeKeyTokens.CornerSmall -> SquircleSmall
}
}
}

/** Converts a shape token key to the local shape provided by the theme */
@Composable
@ReadOnlyComposable
internal fun HedvigShapeKeyTokens.toShape(): Shape {
return MaterialTheme.shapes.fromToken(this)
return MaterialTheme.shapes.fromToken(this, UseSimplerShapesForOldAndroidVersions.current)
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ private fun DragHandle(modifier: Modifier = Modifier) {
.width(40.dp)
.height(4.dp)
.background(
shape = ShapeDefaults.CornerSmall,
shape = HedvigTheme.shapes.cornerSmall,
color = bottomSheetColors.chipColor,
).clip(ShapeDefaults.CornerSmall),
).clip(HedvigTheme.shapes.cornerSmall),
) {}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,58 @@ import androidx.compose.runtime.Immutable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Shape
import com.hedvig.android.compose.ui.UseSimplerShapesForOldAndroidVersions
import com.hedvig.android.design.system.hedvig.tokens.ShapeKeyTokens
import com.hedvig.android.design.system.hedvig.tokens.ShapeTokens
import com.hedvig.android.design.system.hedvig.tokens.ShapeTokens.CornerTopOnlyXLarge

@Immutable
data class Shapes(
val cornerXXLarge: Shape = ShapeDefaults.CornerXXLarge,
val cornerXLarge: Shape = ShapeDefaults.CornerXLarge,
val cornerLarge: Shape = ShapeDefaults.CornerLarge,
val cornerMedium: Shape = ShapeDefaults.CornerMedium,
val cornerSmall: Shape = ShapeDefaults.CornerSmall,
val cornerExtraSmall: Shape = ShapeDefaults.CornerExtraSmall,
val cornerNone: Shape = ShapeDefaults.CornerNone,
val cornerXXLarge: Shape = ShapeTokens.CornerXXLarge,
val cornerXLarge: Shape = ShapeTokens.CornerXLarge,
val cornerLarge: Shape = ShapeTokens.CornerLarge,
val cornerMedium: Shape = ShapeTokens.CornerMedium,
val cornerSmall: Shape = ShapeTokens.CornerSmall,
val cornerExtraSmall: Shape = ShapeTokens.CornerExtraSmall,
val cornerNone: Shape = ShapeTokens.CornerNone,
val roundedCornerXXLarge: Shape = ShapeTokens.RoundedCornerXXLarge,
val roundedCornerXLarge: Shape = ShapeTokens.RoundedCornerXLarge,
val roundedCornerLarge: Shape = ShapeTokens.RoundedCornerLarge,
val roundedCornerMedium: Shape = ShapeTokens.RoundedCornerMedium,
val roundedCornerSmall: Shape = ShapeTokens.RoundedCornerSmall,
val roundedCornerExtraSmall: Shape = ShapeTokens.RoundedCornerExtraSmall,
val roundedCornerTopOnlyXLarge: Shape = ShapeTokens.RoundedCornerTopOnlyXLarge,
)

object ShapeDefaults {
val CornerXXLarge: Shape = ShapeTokens.CornerXXLarge
val CornerXLarge: Shape = ShapeTokens.CornerXLarge
val CornerLarge: Shape = ShapeTokens.CornerLarge
val CornerMedium: Shape = ShapeTokens.CornerMedium
val CornerSmall: Shape = ShapeTokens.CornerSmall
val CornerExtraSmall: Shape = ShapeTokens.CornerExtraSmall
val CornerNone: Shape = ShapeTokens.CornerNone
}

internal fun Shapes.fromToken(value: ShapeKeyTokens): Shape {
return when (value) {
ShapeKeyTokens.CornerXXLarge -> cornerXXLarge
ShapeKeyTokens.CornerXLarge -> cornerXLarge
ShapeKeyTokens.CornerLarge -> cornerLarge
ShapeKeyTokens.CornerMedium -> cornerMedium
ShapeKeyTokens.CornerSmall -> cornerSmall
ShapeKeyTokens.CornerExtraSmall -> cornerExtraSmall
ShapeKeyTokens.CornerNone -> cornerNone
ShapeKeyTokens.CornerTopOnlyXLarge -> CornerTopOnlyXLarge
internal fun Shapes.fromToken(token: ShapeKeyTokens, useSimplerShapes: Boolean): Shape {
return if (useSimplerShapes) {
when (token) {
ShapeKeyTokens.CornerXXLarge -> roundedCornerXXLarge
ShapeKeyTokens.CornerXLarge -> roundedCornerXLarge
ShapeKeyTokens.CornerLarge -> roundedCornerLarge
ShapeKeyTokens.CornerMedium -> roundedCornerMedium
ShapeKeyTokens.CornerSmall -> roundedCornerSmall
ShapeKeyTokens.CornerExtraSmall -> roundedCornerExtraSmall
ShapeKeyTokens.CornerNone -> cornerNone
ShapeKeyTokens.CornerTopOnlyXLarge -> roundedCornerTopOnlyXLarge
}
} else {
when (token) {
ShapeKeyTokens.CornerXXLarge -> cornerXXLarge
ShapeKeyTokens.CornerXLarge -> cornerXLarge
ShapeKeyTokens.CornerLarge -> cornerLarge
ShapeKeyTokens.CornerMedium -> cornerMedium
ShapeKeyTokens.CornerSmall -> cornerSmall
ShapeKeyTokens.CornerExtraSmall -> cornerExtraSmall
ShapeKeyTokens.CornerNone -> cornerNone
ShapeKeyTokens.CornerTopOnlyXLarge -> CornerTopOnlyXLarge
}
}
}

internal val ShapeKeyTokens.value: Shape
@Composable
@ReadOnlyComposable
get() = HedvigTheme.shapes.fromToken(this)
get() = HedvigTheme.shapes.fromToken(this, UseSimplerShapesForOldAndroidVersions.current)

internal val LocalShapes = staticCompositionLocalOf { Shapes() }
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ private fun ToggleBackground(
) {
Surface(
color = color,
shape = ShapeDefaults.CornerLarge,
shape = HedvigTheme.shapes.cornerLarge,
modifier = modifier,
) {
Box(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.hedvig.android.design.system.hedvig.tokens

import androidx.annotation.FloatRange
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Path
Expand All @@ -24,6 +26,17 @@ internal object ShapeTokens {
val CornerExtraSmall: Shape = FigmaShape(6.dp)
val CornerNone: Shape = RectangleShape
val CornerTopOnlyXLarge: Shape = SquircleTopShape(16.dp)

val RoundedCornerXXLarge: Shape = RoundedCornerShape(24.dp)
val RoundedCornerXLarge: Shape = RoundedCornerShape(16.dp)
val RoundedCornerLarge: Shape = RoundedCornerShape(12.dp)
val RoundedCornerMedium: Shape = RoundedCornerShape(10.dp)
val RoundedCornerSmall: Shape = RoundedCornerShape(8.dp)
val RoundedCornerExtraSmall: Shape = RoundedCornerShape(6.dp)
val RoundedCornerTopOnlyXLarge: Shape = RoundedCornerShape(16.dp).copy(
bottomStart = CornerSize(0),
bottomEnd = CornerSize(0),
)
}

private fun RoundedPolygon.Companion.squircle(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ private fun EditCoInsuredScreen(
shape = MaterialTheme.shapes.squircleLargeTop,
sheetState = sheetState,
tonalElevation = 0.dp,
windowInsets = BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top),
contentWindowInsets = { BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top) },
) {
AddCoInsuredBottomSheetContent(
bottomSheetState = uiState.addBottomSheetState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ private fun EditCoInsuredScreen(
shape = MaterialTheme.shapes.squircleLargeTop,
sheetState = sheetState,
tonalElevation = 0.dp,
windowInsets = BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top),
contentWindowInsets = { BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top) },
) {
AddCoInsuredBottomSheetContent(
bottomSheetState = uiState.addBottomSheetState,
Expand Down Expand Up @@ -199,7 +199,7 @@ private fun EditCoInsuredScreen(
shape = MaterialTheme.shapes.squircleLargeTop,
sheetState = sheetState,
tonalElevation = 0.dp,
windowInsets = BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top),
contentWindowInsets = { BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top) },
) {
RemoveCoInsuredBottomSheetContent(
onRemove = { onRemoveCoInsured(it) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ internal fun CoverageTab(
shape = MaterialTheme.shapes.squircleLargeTop,
sheetState = sheetState,
tonalElevation = 0.dp,
windowInsets = BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top),
contentWindowInsets = { BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top) },
) {
Column(
Modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ internal fun YourInfoTab(
shape = MaterialTheme.shapes.squircleLargeTop,
sheetState = sheetState,
tonalElevation = 0.dp,
windowInsets = BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top),
contentWindowInsets = { BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top) },
) {
EditInsuranceBottomSheetContent(
allowChangeAddress = allowChangeAddress,
Expand Down Expand Up @@ -148,7 +148,7 @@ internal fun YourInfoTab(
shape = MaterialTheme.shapes.squircleLargeTop,
sheetState = sheetState,
tonalElevation = 0.dp,
windowInsets = BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top),
contentWindowInsets = { BottomSheetDefaults.windowInsets.only(WindowInsetsSides.Top) },
) {
UpcomingChangesBottomSheetContent(
infoText = stringResource(
Expand Down
Loading

0 comments on commit 3748641

Please sign in to comment.