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.
This commit is contained in:
1 parent
7dedfad68d
commit
36d58085d7
2 files changed
+48
-23
No files matched your search
@@ -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,23 +315,16 @@ 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) {
|
||||
SelectionContainer {
|
||||
@@ -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 }
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in new issue
Block a user