From c4e4664542db8c10626e6f6fd53f978f65a9b2b8 Mon Sep 17 00:00:00 2001 From: OneWay Date: Sun, 4 Oct 2026 12:21:00 +0000 Subject: [PATCH] feat(article): adaptive compact top bar Top-align the title row in compact layouts, align the back button with the first title line using the shared back button, make the title start padding depend on whether the back button is shown, and drop the spacing constant the old arrow buttons used. --- .../research/ui/article/ArticleScreen.kt | 72 +++++++++++++------ .../com/example/research/ui/theme/Spacing.kt | 1 - 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/example/research/ui/article/ArticleScreen.kt b/app/src/main/java/com/example/research/ui/article/ArticleScreen.kt index c97f006..68c04da 100644 --- a/app/src/main/java/com/example/research/ui/article/ArticleScreen.kt +++ b/app/src/main/java/com/example/research/ui/article/ArticleScreen.kt @@ -2,33 +2,59 @@ package com.example.research.ui.article import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.material3.* -import androidx.compose.runtime.* +import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.material3.Button +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.key +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow +import androidx.compose.runtime.withFrameNanos import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.luminance import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.testTag -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTagsAsResourceId -import androidx.compose.ui.unit.dp import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.LineHeightStyle import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.dp import com.example.research.R +import com.example.research.common.ui.AppBackButton import com.example.research.common.ui.theme.dictionaryTitleLarge -import com.example.research.ui.theme.Spacing import com.example.research.ui.theme.AppWindowInsets +import com.example.research.ui.theme.Spacing private const val MERGED_BLOCK_MAX_CHARS = 1500 private const val MERGED_BLOCK_MAX_ITEMS = 12 @@ -263,7 +289,14 @@ fun ArticleTitleBar( null -> "" } - val backIcon = painterResource(R.drawable.ic_arrow_back) + val backButtonOffset = if (compact) { + val titleLineHeight = with(LocalDensity.current) { + MaterialTheme.typography.dictionaryTitleLarge.lineHeight.toDp() + } + Modifier.offset(y = (titleLineHeight - 48.dp) / 2) + } else { + Modifier + } Surface( color = MaterialTheme.colorScheme.surface, @@ -282,22 +315,15 @@ fun ArticleTitleBar( .height(Spacing.topBarHeight) } ), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = if (compact) Alignment.Top else Alignment.CenterVertically ) { if (showBackButton) { - Box( + AppBackButton( + onClick = onNavigateBack, modifier = Modifier - .padding(start = Spacing.iconStart) - .size(24.dp) - .clickable(onClick = onNavigateBack), - contentAlignment = Alignment.Center - ) { - Icon( - painter = backIcon, - contentDescription = stringResource(R.string.action_back), - modifier = Modifier.size(24.dp) - ) - } + .padding(start = 10.dp) + .then(backButtonOffset) + ) } key(selectionReset) { @@ -309,7 +335,7 @@ fun ArticleTitleBar( maxLines = 1, overflow = TextOverflow.Ellipsis, modifier = Modifier - .padding(start = if (showBackButton) Spacing.searchTextStart - Spacing.iconStart - 24.dp else 16.dp) + .padding(start = if (showBackButton) 0.dp else 16.dp) .testTag("article_title") .semantics { testTagsAsResourceId = true } ) diff --git a/app/src/main/java/com/example/research/ui/theme/Spacing.kt b/app/src/main/java/com/example/research/ui/theme/Spacing.kt index 3d2b033..baf6172 100644 --- a/app/src/main/java/com/example/research/ui/theme/Spacing.kt +++ b/app/src/main/java/com/example/research/ui/theme/Spacing.kt @@ -6,7 +6,6 @@ object Spacing { // Semantic spacing constants for specific UI elements val topBarPadding = 8.dp val topBarHeight = 56.dp - val iconStart = 32.dp val searchTextStart = 68.dp val listItemVertical = 8.dp