mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-14 08:17:04 +05:30
android: replace ClawFab with a NavigationBar interaction
This commit is contained in:
parent
f8a32ccd2c
commit
b8a6cf90c8
5 changed files with 11 additions and 94 deletions
|
@ -10,11 +10,8 @@ import androidx.compose.runtime.LaunchedEffect
|
|||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
|
@ -31,7 +28,6 @@ import com.google.accompanist.insets.statusBarsPadding
|
|||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import dev.msfjarvis.claw.android.R
|
||||
import dev.msfjarvis.claw.android.ui.decorations.ClawAppBar
|
||||
import dev.msfjarvis.claw.android.ui.decorations.ClawFab
|
||||
import dev.msfjarvis.claw.android.ui.decorations.ClawNavigationBar
|
||||
import dev.msfjarvis.claw.android.ui.decorations.NavigationItem
|
||||
import dev.msfjarvis.claw.android.ui.lists.DatabasePosts
|
||||
|
@ -44,6 +40,7 @@ import dev.msfjarvis.claw.common.comments.HTMLConverter
|
|||
import dev.msfjarvis.claw.common.comments.LocalHTMLConverter
|
||||
import dev.msfjarvis.claw.common.theme.LobstersTheme
|
||||
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
|
@ -53,14 +50,12 @@ fun LobstersApp(
|
|||
htmlConverter: HTMLConverter,
|
||||
setWebUri: (String?) -> Unit,
|
||||
) {
|
||||
var isFabVisible by remember { mutableStateOf(false) }
|
||||
|
||||
val systemUiController = rememberSystemUiController()
|
||||
val networkListState = rememberLazyListState()
|
||||
val savedListState = rememberLazyListState()
|
||||
val navController = rememberNavController()
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val postActions = rememberPostActions(urlLauncher, navController, viewModel)
|
||||
val nestedScrollConnection = rememberNestedScrollConnection { isFabVisible = it }
|
||||
val currentDestination by currentNavigationDestination(navController)
|
||||
|
||||
val networkPosts = viewModel.pagerFlow.collectAsLazyPagingItems()
|
||||
|
@ -81,12 +76,12 @@ fun LobstersApp(
|
|||
label = "Hottest",
|
||||
route = Destinations.Hottest.getRoute(),
|
||||
icon = painterResource(R.drawable.ic_whatshot_24dp),
|
||||
),
|
||||
) { coroutineScope.launch { networkListState.animateScrollToItem(index = 0) } },
|
||||
NavigationItem(
|
||||
label = "Saved",
|
||||
route = Destinations.Saved.getRoute(),
|
||||
icon = painterResource(commonR.drawable.ic_favorite_24dp),
|
||||
),
|
||||
) { coroutineScope.launch { savedListState.animateScrollToItem(index = 0) } },
|
||||
)
|
||||
|
||||
SideEffect { systemUiController.setStatusBarColor(color = systemBarsColor) }
|
||||
|
@ -109,12 +104,6 @@ fun LobstersApp(
|
|||
modifier = Modifier.statusBarsPadding(),
|
||||
)
|
||||
},
|
||||
floatingActionButton = {
|
||||
ClawFab(
|
||||
isFabVisible = isFabVisible && currentDestination == Destinations.Hottest.getRoute(),
|
||||
listState = networkListState,
|
||||
)
|
||||
},
|
||||
bottomBar = {
|
||||
ClawNavigationBar(
|
||||
navController = navController,
|
||||
|
@ -136,7 +125,6 @@ fun LobstersApp(
|
|||
isPostSaved = viewModel::isPostSaved,
|
||||
reloadPosts = viewModel::reloadPosts,
|
||||
postActions = postActions,
|
||||
modifier = Modifier.nestedScroll(nestedScrollConnection),
|
||||
)
|
||||
}
|
||||
composable(Destinations.Saved.getRoute()) {
|
||||
|
@ -146,9 +134,7 @@ fun LobstersApp(
|
|||
listState = savedListState,
|
||||
isSaved = viewModel::isPostSaved,
|
||||
postActions = postActions,
|
||||
modifier =
|
||||
Modifier.nestedScroll(nestedScrollConnection)
|
||||
.padding(bottom = paddingValues.calculateBottomPadding()),
|
||||
modifier = Modifier.padding(bottom = paddingValues.calculateBottomPadding()),
|
||||
)
|
||||
}
|
||||
composable(Destinations.Comments.getRoute("{postId}")) { backStackEntry ->
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
package dev.msfjarvis.claw.android.ui.decorations
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import dev.msfjarvis.claw.android.R
|
||||
import dev.msfjarvis.claw.android.ui.slideInAnimation
|
||||
import dev.msfjarvis.claw.android.ui.slideOutAnimation
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
fun ClawFab(
|
||||
isFabVisible: Boolean,
|
||||
listState: LazyListState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
AnimatedVisibility(
|
||||
visible = isFabVisible,
|
||||
enter = slideInAnimation(),
|
||||
exit = slideOutAnimation(),
|
||||
modifier = modifier,
|
||||
) {
|
||||
FloatingActionButton(onClick = { coroutineScope.launch { listState.animateScrollToItem(0) } }) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_arrow_upward_24dp),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,7 +33,10 @@ fun ClawNavigationBar(
|
|||
label = { Text(text = navItem.label) },
|
||||
selected = navController.currentDestination?.route == navItem.route,
|
||||
onClick = {
|
||||
if (navController.currentDestination?.route == navItem.route) return@NavigationBarItem
|
||||
if (navController.currentDestination?.route == navItem.route) {
|
||||
navItem.listStateResetCallback()
|
||||
return@NavigationBarItem
|
||||
}
|
||||
navController.popBackStack(navController.graph.startDestinationRoute!!, false)
|
||||
if (navItem.route != Destinations.startDestination.getRoute()) {
|
||||
navController.navigate(navItem.route)
|
||||
|
@ -49,4 +52,5 @@ class NavigationItem(
|
|||
val label: String,
|
||||
val route: String,
|
||||
val icon: Painter,
|
||||
val listStateResetCallback: () -> Unit,
|
||||
)
|
||||
|
|
|
@ -18,11 +18,8 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.compositeOver
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import dev.msfjarvis.claw.android.ui.navigation.Destinations
|
||||
|
@ -108,28 +105,6 @@ fun rememberPostActions(
|
|||
}
|
||||
}
|
||||
|
||||
private const val ScrollDelta = 50
|
||||
|
||||
@Composable
|
||||
fun rememberNestedScrollConnection(setVisibility: (Boolean) -> Unit): NestedScrollConnection {
|
||||
return remember {
|
||||
object : NestedScrollConnection {
|
||||
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
|
||||
val delta = available.y
|
||||
|
||||
if (delta > ScrollDelta) {
|
||||
setVisibility(true)
|
||||
} else if (delta < -ScrollDelta) {
|
||||
setVisibility(false)
|
||||
}
|
||||
|
||||
// We didn't consume any offset here so return Offset.Zero
|
||||
return Offset.Zero
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [ColorScheme.surface] color with an alpha of the [ColorScheme.primary] color overlaid
|
||||
* on top of it. Computes the surface tonal color at different elevation levels e.g. surface1
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M4,12l1.41,1.41L11,7.83V20h2V7.83l5.58,5.59L20,12l-8,-8 -8,8z"/>
|
||||
</vector>
|
Loading…
Add table
Add a link
Reference in a new issue