feat(ui): click on top bar to scroll back to top

This commit is contained in:
junkfood 2024-11-12 20:27:07 +08:00
parent fe22c445f0
commit 05b249b708
No known key found for this signature in database
GPG Key ID: 2EA5B648DB112A34
3 changed files with 125 additions and 81 deletions

View File

@ -17,17 +17,19 @@ import me.ash.reader.ui.theme.palette.onDark
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RYScaffold(
modifier: Modifier = Modifier,
containerColor: Color = MaterialTheme.colorScheme.surface,
topBarTonalElevation: Dp = 0.dp,
containerTonalElevation: Dp = 0.dp,
navigationIcon: (@Composable () -> Unit)? = null,
actions: (@Composable RowScope.() -> Unit)? = null,
topBar: (@Composable () -> Unit)? = null,
bottomBar: (@Composable () -> Unit)? = null,
floatingActionButton: (@Composable () -> Unit)? = null,
content: @Composable () -> Unit = {},
) {
Scaffold(
modifier = Modifier
modifier = modifier
.background(
MaterialTheme.colorScheme.surfaceColorAtElevation(
topBarTonalElevation,
@ -39,7 +41,7 @@ fun RYScaffold(
color = containerColor
) onDark MaterialTheme.colorScheme.surface,
topBar = {
if (navigationIcon != null || actions != null) {
if (topBar != null) topBar() else if (navigationIcon != null || actions != null) {
TopAppBar(
title = {},
navigationIcon = { navigationIcon?.invoke() },

View File

@ -2,6 +2,7 @@ package me.ash.reader.ui.page.home.feeds
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@ -31,6 +32,8 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
import androidx.compose.runtime.Composable
@ -76,6 +79,7 @@ import me.ash.reader.ui.ext.currentAccountId
import me.ash.reader.ui.ext.findActivity
import me.ash.reader.ui.ext.getCurrentVersion
import me.ash.reader.ui.ext.getDefaultGroupId
import me.ash.reader.ui.ext.surfaceColorAtElevation
import me.ash.reader.ui.page.common.RouteName
import me.ash.reader.ui.page.home.FilterState
import me.ash.reader.ui.page.home.HomeViewModel
@ -207,6 +211,20 @@ fun FeedsPage(
RYScaffold(
topBarTonalElevation = topBarTonalElevation.value.dp,
containerTonalElevation = groupListTonalElevation.value.dp,
topBar = {
TopAppBar(
modifier = Modifier.clickable(
onClick = {
scope.launch {
if (listState.firstVisibleItemIndex != 0) {
listState.animateScrollToItem(0)
}
}
},
indication = null,
interactionSource = remember { MutableInteractionSource() }
),
title = {},
navigationIcon = {
FeedbackIconButton(
modifier = Modifier.size(20.dp),
@ -231,6 +249,13 @@ fun FeedsPage(
}
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
topBarTonalElevation.value.dp
),
)
)
},
content = {
PullToRefreshBox(
state = syncingState,

View File

@ -1,6 +1,8 @@
package me.ash.reader.ui.page.home.flow
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
@ -15,7 +17,10 @@ import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material.icons.rounded.DoneAll
import androidx.compose.material.icons.rounded.Search
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
import androidx.compose.runtime.Composable
@ -61,6 +66,7 @@ import me.ash.reader.ui.component.base.FeedbackIconButton
import me.ash.reader.ui.component.base.RYExtensibleVisibility
import me.ash.reader.ui.component.base.RYScaffold
import me.ash.reader.ui.ext.collectAsStateValue
import me.ash.reader.ui.ext.surfaceColorAtElevation
import me.ash.reader.ui.page.common.RouteName
import me.ash.reader.ui.page.home.HomeViewModel
@ -228,6 +234,20 @@ fun FlowPage(
RYScaffold(
topBarTonalElevation = topBarTonalElevation.value.dp,
containerTonalElevation = articleListTonalElevation.value.dp,
topBar = {
TopAppBar(
modifier = Modifier.clickable(
onClick = {
scope.launch {
if (listState.firstVisibleItemIndex != 0) {
listState.animateScrollToItem(0)
}
}
},
indication = null,
interactionSource = remember { MutableInteractionSource() }
),
title = {},
navigationIcon = {
FeedbackIconButton(
imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
@ -256,11 +276,8 @@ fun FlowPage(
},
) {
scope.launch {
// java.lang.NullPointerException: Attempt to invoke virtual method
// 'boolean androidx.compose.ui.node.LayoutNode.getNeedsOnPositionedDispatch$ui_release()'
// on a null object reference
if (flowUiState.listState.firstVisibleItemIndex != 0) {
flowUiState.listState.scrollToItem(0)
flowUiState.listState.animateScrollToItem(0)
}
markAsRead = !markAsRead
onSearch = false
@ -277,15 +294,18 @@ fun FlowPage(
},
) {
scope.launch {
// java.lang.NullPointerException: Attempt to invoke virtual method
// 'boolean androidx.compose.ui.node.LayoutNode.getNeedsOnPositionedDispatch$ui_release()'
// on a null object reference
if (flowUiState.listState.firstVisibleItemIndex != 0) {
flowUiState.listState.scrollToItem(0)
flowUiState.listState.animateScrollToItem(0)
}
onSearch = !onSearch
}
}
}, colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
topBarTonalElevation.value.dp
),
)
)
},
content = {
PullToRefreshBox(
@ -394,9 +414,6 @@ fun FlowPage(
filterBarTonalElevation = filterBarTonalElevation.value.dp,
) {
scope.launch {
// java.lang.NullPointerException: Attempt to invoke virtual method
// 'boolean androidx.compose.ui.node.LayoutNode.getNeedsOnPositionedDispatch$ui_release()'
// on a null object reference
if (flowUiState.listState.firstVisibleItemIndex != 0) {
flowUiState.listState.animateScrollToItem(0)
}