From 9a31b659d0e126108e675a348e230673c640c99c Mon Sep 17 00:00:00 2001 From: JackEblan Date: Sun, 15 Sep 2024 10:04:34 +0800 Subject: [PATCH] Adaptive score screen --- .../kotlin/AndroidFeatureConventionPlugin.kt | 1 + .../feature/question/screen/ScoreScreen.kt | 158 +++++++++++++----- gradle/libs.versions.toml | 6 +- 3 files changed, 125 insertions(+), 40 deletions(-) diff --git a/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt index 297b6649..98e23df3 100644 --- a/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt @@ -44,6 +44,7 @@ class AndroidFeatureConventionPlugin : Plugin { add("implementation", project(":core:design-system")) add("implementation", project(":core:ui")) + add("implementation", libs.findLibrary("androidx.compose.material3.adaptive").get()) add("implementation", libs.findLibrary("androidx.hilt.navigation.compose").get()) add("implementation", libs.findLibrary("androidx.lifecycle.runtime.compose").get()) add("implementation", libs.findLibrary("androidx.lifecycle.viewmodel.compose").get()) diff --git a/feature/question/src/main/kotlin/com/eblan/socialworkreviewer/feature/question/screen/ScoreScreen.kt b/feature/question/src/main/kotlin/com/eblan/socialworkreviewer/feature/question/screen/ScoreScreen.kt index c08d3da4..cc2fc88b 100644 --- a/feature/question/src/main/kotlin/com/eblan/socialworkreviewer/feature/question/screen/ScoreScreen.kt +++ b/feature/question/src/main/kotlin/com/eblan/socialworkreviewer/feature/question/screen/ScoreScreen.kt @@ -21,6 +21,7 @@ import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize @@ -33,6 +34,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ProgressIndicatorDefaults import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -43,6 +45,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.unit.dp +import androidx.window.core.layout.WindowHeightSizeClass +import androidx.window.core.layout.WindowSizeClass import com.eblan.socialworkreviewer.core.designsystem.icon.Swr import com.eblan.socialworkreviewer.core.designsystem.theme.LocalGradientColors import com.eblan.socialworkreviewer.core.model.Question @@ -52,6 +56,7 @@ import kotlin.math.roundToInt @Composable internal fun ScoreScreen( modifier: Modifier = Modifier, + windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().windowSizeClass, score: Int, questions: List, minutes: String?, @@ -88,44 +93,21 @@ internal fun ScoreScreen( .consumeWindowInsets(paddingValues) .padding(paddingValues), ) { - Column( - modifier = modifier - .fillMaxSize() - .padding(10.dp), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - AverageCircularProgressIndicator( - progress = { (average / 100).toFloat() }, - modifier = Modifier.size(150.dp), - strokeWidth = 8.dp, - strokeCap = StrokeCap.Round, - trackColor = ProgressIndicatorDefaults.linearTrackColor, - ) { - Text( - modifier = Modifier.padding(5.dp), - text = "${average.roundToInt()}%", - style = MaterialTheme.typography.titleLarge.copy( - brush = Brush.linearGradient( - colors = LocalGradientColors.current.topBarTitleColorsDefault, - ), - ), - ) - } - - Spacer(modifier = Modifier.height(20.dp)) - - InfoText(title = "Correct", subtitle = "$score") - - Spacer(modifier = Modifier.height(20.dp)) - - InfoText(title = "Wrong", subtitle = "${questions.size - score}") - - Spacer(modifier = Modifier.height(20.dp)) - - InfoText( - title = "Time", - subtitle = if (minutes.isNullOrBlank()) "Time's up!" else minutes, + if (windowSizeClass.windowHeightSizeClass != WindowHeightSizeClass.COMPACT) { + ColumnScoreScreen( + modifier = modifier, + average = average, + score = score, + questions = questions, + minutes = minutes, + ) + } else { + RowScoreScreen( + modifier = modifier, + average = average, + score = score, + questions = questions, + minutes = minutes, ) } } @@ -147,6 +129,106 @@ internal fun ScoreScreen( } } +@Composable +private fun ColumnScoreScreen( + modifier: Modifier, + average: Double, + score: Int, + questions: List, + minutes: String?, +) { + Column( + modifier = modifier + .fillMaxSize() + .padding(10.dp), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + AverageCircularProgressIndicator( + progress = { (average / 100).toFloat() }, + modifier = Modifier.size(150.dp), + strokeWidth = 8.dp, + strokeCap = StrokeCap.Round, + trackColor = ProgressIndicatorDefaults.linearTrackColor, + ) { + Text( + modifier = Modifier.padding(5.dp), + text = "${average.roundToInt()}%", + style = MaterialTheme.typography.titleLarge.copy( + brush = Brush.linearGradient( + colors = LocalGradientColors.current.topBarTitleColorsDefault, + ), + ), + ) + } + + Spacer(modifier = Modifier.height(20.dp)) + + InfoText(title = "Correct", subtitle = "$score") + + Spacer(modifier = Modifier.height(20.dp)) + + InfoText(title = "Wrong", subtitle = "${questions.size - score}") + + Spacer(modifier = Modifier.height(20.dp)) + + InfoText( + title = "Time", + subtitle = if (minutes.isNullOrBlank()) "Time's up!" else minutes, + ) + } +} + +@Composable +private fun RowScoreScreen( + modifier: Modifier, + average: Double, + score: Int, + questions: List, + minutes: String?, +) { + Row( + modifier = modifier + .fillMaxSize() + .padding(10.dp), + horizontalArrangement = Arrangement.SpaceAround, + verticalAlignment = Alignment.CenterVertically, + ) { + AverageCircularProgressIndicator( + progress = { (average / 100).toFloat() }, + modifier = Modifier.size(150.dp), + strokeWidth = 8.dp, + strokeCap = StrokeCap.Round, + trackColor = ProgressIndicatorDefaults.linearTrackColor, + ) { + Text( + modifier = Modifier.padding(5.dp), + text = "${average.roundToInt()}%", + style = MaterialTheme.typography.titleLarge.copy( + brush = Brush.linearGradient( + colors = LocalGradientColors.current.topBarTitleColorsDefault, + ), + ), + ) + } + + Spacer(modifier = Modifier.height(20.dp)) + + InfoText(title = "Correct", subtitle = "$score") + + Spacer(modifier = Modifier.height(20.dp)) + + InfoText(title = "Wrong", subtitle = "${questions.size - score}") + + Spacer(modifier = Modifier.height(20.dp)) + + InfoText( + title = "Time", + subtitle = if (minutes.isNullOrBlank()) "Time's up!" else minutes, + ) + } +} + @Composable private fun InfoText(modifier: Modifier = Modifier, title: String, subtitle: String) { Column( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5c91b864..784182da 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,6 @@ androidGradlePlugin = "8.4.0" androidTools = "31.3.0" androidxActivity = "1.9.0" androidxComposeBom = "2024.09.00" -androidxComposeMaterial3AdaptiveNavigationSuite = "1.3.0" androidxCoreKtx = "1.13.1" androidxCoreSplashscreen = "1.0.1" androidxDataStore = "1.0.0" @@ -53,7 +52,10 @@ androidx-compose-foundation = { group = "androidx.compose.foundation", name = "f androidx-compose-foundation-layout = { group = "androidx.compose.foundation", name = "foundation-layout" } androidx-compose-material = { group = "androidx.compose.material", name = "material" } androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } -androidx-compose-material3-adaptive-navigation-suite = { group = "androidx.compose.material3", name = "material3-adaptive-navigation-suite", version.ref = "androidxComposeMaterial3AdaptiveNavigationSuite" } +androidx-compose-material3-adaptive-navigation-suite = { group = "androidx.compose.material3", name = "material3-adaptive-navigation-suite" } +androidx-compose-material3-adaptive = { group = "androidx.compose.material3.adaptive", name = "adaptive" } +androidx-compose-material3-adaptive-layout = { group = "androidx.compose.material3.adaptive", name = "adaptive-layout" } +androidx-compose-material3-adaptive-navigation = { group = "androidx.compose.material3.adaptive", name = "adaptive-navigation" } androidx-compose-material-iconsExtended = { group = "androidx.compose.material", name = "material-icons-extended" } androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime" } androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }