use experimental rail
This commit is contained in:
+4
@@ -39,3 +39,7 @@ fun createNavigationList(): List<NavigationEntry<Route>> {
|
||||
)
|
||||
return list
|
||||
}
|
||||
|
||||
fun List<NavigationEntry<*>>.findTitle(route: Route): String? {
|
||||
return firstOrNull { it.route == route }?.title
|
||||
}
|
||||
|
||||
+44
-95
@@ -1,147 +1,96 @@
|
||||
package ru.shadowsparky.vbox.shared.presentation
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.LargeTopAppBar
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import ru.shadowsparky.ui.BaseScreen
|
||||
import ru.shadowsparky.ui.LocalBlurState
|
||||
import ru.shadowsparky.ui.USE_EXPERIMENTAL_RAIL
|
||||
import ru.shadowsparky.ui.applyBlurEffect
|
||||
import ru.shadowsparky.ui.components.isTv
|
||||
import ru.shadowsparky.ui.currentWindowType
|
||||
import ru.shadowsparky.ui.isCompact
|
||||
import ru.shadowsparky.ui.isExpanded
|
||||
import ru.shadowsparky.ui.rememberBlurState
|
||||
import ru.shadowsparky.ui.theme.ComponentDefaults
|
||||
import ru.shadowsparky.vbox.shared.presentation.list.VideoContent
|
||||
import ru.shadowsparky.vbox.shared.presentation.nav.Child
|
||||
import ru.shadowsparky.vbox.shared.presentation.nav.Route
|
||||
import ru.shadowsparky.vbox.shared.presentation.saved.SavedMovieContent
|
||||
import ru.shadowsparky.vbox.shared.presentation.search.SearchAppBar
|
||||
import ru.shadowsparky.vbox.shared.presentation.search.SearchVideoContent
|
||||
import ru.shadowsparky.vbox.shared.presentation.saved.SavedMovieScreen
|
||||
import ru.shadowsparky.vbox.shared.presentation.search.SearchScreen
|
||||
import ru.shadowsparky.vbox.shared.presentation.settings.SettingsContent
|
||||
|
||||
@Composable
|
||||
fun MainScreen(
|
||||
route: Route,
|
||||
child: Child,
|
||||
rootComponent: RootComponent
|
||||
) {
|
||||
if (child is Child.SearchChild) {
|
||||
SearchScreenInternal(child, route, rootComponent)
|
||||
} else {
|
||||
MainScreenInternal(route, child, rootComponent)
|
||||
fun MainScreen(route: Route, child: Child, rootComponent: RootComponent) {
|
||||
when (child) {
|
||||
is Child.SearchChild -> SearchScreen(child.component, route) { rootComponent.nav(it, true) }
|
||||
is Child.SavedMovieChild -> SavedMovieScreen(child.component, route) { rootComponent.navReplace(it) }
|
||||
else -> MainScreenInternal(route, child) { rootComponent.navReplace(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun SearchScreenInternal(
|
||||
child: Child.SearchChild,
|
||||
fun BaseMainScreen(
|
||||
appBar: @Composable () -> Unit,
|
||||
route: Route,
|
||||
rootComponent: RootComponent,
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
onNavigate: (Route) -> Unit,
|
||||
content: @Composable (PaddingValues) -> Unit
|
||||
) {
|
||||
val component = child.component
|
||||
var textFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
|
||||
mutableStateOf(TextFieldValue())
|
||||
}
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
|
||||
val requester by remember { mutableStateOf(FocusRequester()) }
|
||||
val windowType = currentWindowType()
|
||||
val searchAppBar: (@Composable () -> Unit) = {
|
||||
SearchAppBar(
|
||||
textFieldValue = textFieldValue,
|
||||
onDone = { component.done(textFieldValue.text) },
|
||||
onValueChange = { textFieldValue = it },
|
||||
focusRequester = requester
|
||||
)
|
||||
}
|
||||
val blurState = rememberBlurState()
|
||||
CompositionLocalProvider(LocalBlurState provides blurState) {
|
||||
BaseScreen(
|
||||
appBar = {
|
||||
if (windowType.isCompact || !USE_EXPERIMENTAL_RAIL) searchAppBar()
|
||||
},
|
||||
appBar = { appBar() },
|
||||
currentRoute = route,
|
||||
onSelectNavigation = { rootComponent.nav(it, true) },
|
||||
onSelectNavigation = { onNavigate(it) },
|
||||
navigationEntries = createNavigationList(),
|
||||
colorScheme = getColorScheme(),
|
||||
scrollBehavior = scrollBehavior
|
||||
) {
|
||||
val content: @Composable () -> Unit = {
|
||||
SearchVideoContent(
|
||||
child.component,
|
||||
it,
|
||||
requester
|
||||
) { textFieldValue = it }
|
||||
}
|
||||
if (windowType.isExpanded && USE_EXPERIMENTAL_RAIL) {
|
||||
Column {
|
||||
searchAppBar()
|
||||
content()
|
||||
}
|
||||
} else {
|
||||
content()
|
||||
}
|
||||
) { padding ->
|
||||
content(padding)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun MainScreenInternal(route: Route, child: Child, rootComponent: RootComponent) {
|
||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||
private fun MainScreenInternal(route: Route, child: Child, onNavigate: (Route) -> Unit) {
|
||||
val navList = createNavigationList()
|
||||
val windowType = currentWindowType()
|
||||
val blurState = rememberBlurState()
|
||||
CompositionLocalProvider(LocalBlurState provides blurState) {
|
||||
BaseScreen(
|
||||
appBar = {
|
||||
if (windowType.isCompact || !USE_EXPERIMENTAL_RAIL) {
|
||||
navList.firstOrNull { it.route == route }?.title?.let {
|
||||
if (isTv()) {
|
||||
TopAppBar(
|
||||
title = { Text(it) },
|
||||
scrollBehavior = scrollBehavior,
|
||||
modifier = Modifier.applyBlurEffect(blurState),
|
||||
colors = ComponentDefaults.topAppBarColors()
|
||||
)
|
||||
} else {
|
||||
LargeTopAppBar(
|
||||
title = { Text(it) },
|
||||
scrollBehavior = scrollBehavior,
|
||||
modifier = Modifier.applyBlurEffect(blurState),
|
||||
colors = ComponentDefaults.topAppBarColors()
|
||||
)
|
||||
}
|
||||
}
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
|
||||
BaseMainScreen(
|
||||
appBar = {
|
||||
navList.findTitle(route)?.let { title ->
|
||||
if (currentWindowType().isCompact) {
|
||||
LargeTopAppBar(
|
||||
title = { Text(title) },
|
||||
scrollBehavior = scrollBehavior,
|
||||
modifier = Modifier.applyBlurEffect(LocalBlurState.current),
|
||||
colors = ComponentDefaults.topAppBarColors()
|
||||
)
|
||||
} else {
|
||||
TopAppBar(
|
||||
title = { Text(title) },
|
||||
scrollBehavior = scrollBehavior,
|
||||
modifier = Modifier.applyBlurEffect(LocalBlurState.current),
|
||||
colors = ComponentDefaults.topAppBarColors()
|
||||
)
|
||||
}
|
||||
},
|
||||
currentRoute = route,
|
||||
onSelectNavigation = { rootComponent.navReplace(it) },
|
||||
navigationEntries = navList,
|
||||
colorScheme = getColorScheme(),
|
||||
scrollBehavior = scrollBehavior
|
||||
) { padding ->
|
||||
}
|
||||
},
|
||||
route = route,
|
||||
scrollBehavior = scrollBehavior,
|
||||
onNavigate = onNavigate,
|
||||
content = { padding ->
|
||||
when (child) {
|
||||
is Child.VideosChild -> VideoContent(child.component, padding)
|
||||
is Child.SettingsChild -> SettingsContent(child.component, padding)
|
||||
is Child.SavedMovieChild -> SavedMovieContent(child.component, padding)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
+2
-23
@@ -10,7 +10,6 @@ import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
@@ -42,7 +41,6 @@ import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
@@ -119,7 +117,6 @@ fun VideoScreenContent(
|
||||
emptyResource: StringResource,
|
||||
onRefresh: () -> Unit,
|
||||
onShowOverview: (Long) -> Unit,
|
||||
extraFab: (@Composable BoxScope.() -> Unit)? = null,
|
||||
onLoad: () -> Unit
|
||||
) {
|
||||
LaunchedEffect(Unit) {
|
||||
@@ -130,7 +127,7 @@ fun VideoScreenContent(
|
||||
onRefresh()
|
||||
}
|
||||
} else if (items != null) {
|
||||
VideosInfo(items = items, paddingValues, emptyResource, extraFab) {
|
||||
VideosInfo(items = items, paddingValues, emptyResource) {
|
||||
onShowOverview(it.id)
|
||||
}
|
||||
} else {
|
||||
@@ -143,16 +140,11 @@ fun VideosInfo(
|
||||
items: List<VideoItem>,
|
||||
paddingValues: PaddingValues,
|
||||
emptyResource: StringResource,
|
||||
extraFab: (@Composable BoxScope.() -> Unit)? = null,
|
||||
onClick: (item: VideoItem) -> Unit
|
||||
) {
|
||||
val blur = LocalBlurState.current
|
||||
val gridState = rememberLazyGridState()
|
||||
val density = LocalDensity.current
|
||||
val layoutDirection = LocalLayoutDirection.current
|
||||
|
||||
var fabHeight by remember { mutableStateOf(0.dp) }
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
if (items.isNotEmpty()) {
|
||||
LazyVerticalGrid(
|
||||
@@ -164,7 +156,7 @@ fun VideosInfo(
|
||||
start = paddingValues.calculateStartPadding(layoutDirection),
|
||||
top = paddingValues.calculateTopPadding(),
|
||||
end = paddingValues.calculateEndPadding(layoutDirection),
|
||||
bottom = paddingValues.calculateBottomPadding() + (fabHeight / 2)
|
||||
bottom = paddingValues.calculateBottomPadding()
|
||||
),
|
||||
state = gridState
|
||||
) {
|
||||
@@ -179,19 +171,6 @@ fun VideosInfo(
|
||||
} else {
|
||||
VideosNotFound(emptyResource)
|
||||
}
|
||||
|
||||
val rootBoxScope = this
|
||||
|
||||
extraFab?.let {
|
||||
Box(
|
||||
modifier = Modifier.align(Alignment.BottomEnd)
|
||||
.onGloballyPositioned { coordinates ->
|
||||
fabHeight = with(density) {
|
||||
coordinates.size.height.toDp()
|
||||
}
|
||||
}
|
||||
) { it(rootBoxScope) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+39
-22
@@ -9,18 +9,19 @@ import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.calculateEndPadding
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -28,19 +29,24 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import ru.shadowsparky.ui.components.LazyColumn
|
||||
import ru.shadowsparky.ui.theme.ComponentDefaults
|
||||
import ru.shadowsparky.vbox.shared.domain.tag.TagInfo
|
||||
import ru.shadowsparky.vbox.shared.presentation.BaseMainScreen
|
||||
import ru.shadowsparky.vbox.shared.presentation.createNavigationList
|
||||
import ru.shadowsparky.vbox.shared.presentation.findTitle
|
||||
import ru.shadowsparky.vbox.shared.presentation.list.VideoScreenContent
|
||||
import ru.shadowsparky.vbox.shared.presentation.nav.Route
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun SavedMovieContent(comp: SavedMovieScreenComponent, paddingValues: PaddingValues) {
|
||||
val items by comp.all.collectAsStateWithLifecycle(null)
|
||||
fun SavedMovieScreen(comp: SavedMovieScreenComponent, route: Route, onNavigate: (Route) -> Unit) {
|
||||
val tags by comp.userTags.collectAsStateWithLifecycle(null)
|
||||
val navList = createNavigationList()
|
||||
var filterBottomSheetVisible by rememberSaveable { mutableStateOf(false) }
|
||||
if (filterBottomSheetVisible) {
|
||||
FilterBottomSheet(
|
||||
@@ -50,6 +56,33 @@ fun SavedMovieContent(comp: SavedMovieScreenComponent, paddingValues: PaddingVal
|
||||
onFilterBy = { comp.filterByTag(it) }
|
||||
)
|
||||
}
|
||||
BaseMainScreen(
|
||||
appBar = {
|
||||
TopAppBar(
|
||||
title = { navList.findTitle(route)?.let { Text(it) } },
|
||||
actions = {
|
||||
IconButton(
|
||||
onClick = { filterBottomSheetVisible = true }
|
||||
) {
|
||||
Icon(
|
||||
painterResource(Res.drawable.filter_list),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
},
|
||||
colors = ComponentDefaults.topAppBarColors()
|
||||
)
|
||||
},
|
||||
route = route,
|
||||
scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(),
|
||||
onNavigate = onNavigate,
|
||||
content = { SavedMovieContent(comp, it) }
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SavedMovieContent(comp: SavedMovieScreenComponent, paddingValues: PaddingValues) {
|
||||
val items by comp.all.collectAsStateWithLifecycle(null)
|
||||
VideoScreenContent(
|
||||
paddingValues,
|
||||
null,
|
||||
@@ -57,23 +90,7 @@ fun SavedMovieContent(comp: SavedMovieScreenComponent, paddingValues: PaddingVal
|
||||
onRefresh = {},
|
||||
onShowOverview = { comp.showOverview(it) },
|
||||
emptyResource = Res.string.saved_movies_not_found,
|
||||
onLoad = {},
|
||||
extraFab = {
|
||||
if (tags?.isNotEmpty() == true) {
|
||||
FloatingActionButton(
|
||||
onClick = { filterBottomSheetVisible = true },
|
||||
modifier = Modifier.padding(
|
||||
end = paddingValues.calculateEndPadding(LocalLayoutDirection.current) + 4.dp,
|
||||
bottom = paddingValues.calculateBottomPadding() + 4.dp
|
||||
)
|
||||
) {
|
||||
Icon(
|
||||
painterResource(Res.drawable.filter_list),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
onLoad = {}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+40
-2
@@ -35,13 +35,17 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TextFieldColors
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.rememberSearchBarState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
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.withFrameNanos
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -62,7 +66,6 @@ import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import kotlinx.coroutines.delay
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import ru.shadowsparky.ui.LocalBlurState
|
||||
@@ -71,7 +74,42 @@ import ru.shadowsparky.ui.applyBlurSource
|
||||
import ru.shadowsparky.ui.components.BackButton
|
||||
import ru.shadowsparky.ui.components.ExpressiveLazyColumn
|
||||
import ru.shadowsparky.ui.theme.ComponentDefaults
|
||||
import ru.shadowsparky.vbox.shared.presentation.BaseMainScreen
|
||||
import ru.shadowsparky.vbox.shared.presentation.imePaddingInternal
|
||||
import ru.shadowsparky.vbox.shared.presentation.nav.Route
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun SearchScreen(
|
||||
component: SearchScreenComponent,
|
||||
route: Route,
|
||||
onNavigate: (Route) -> Unit
|
||||
) {
|
||||
val requester by remember { mutableStateOf(FocusRequester()) }
|
||||
var textFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
|
||||
mutableStateOf(TextFieldValue())
|
||||
}
|
||||
BaseMainScreen(
|
||||
appBar = {
|
||||
SearchAppBar(
|
||||
textFieldValue = textFieldValue,
|
||||
onDone = { component.done(textFieldValue.text) },
|
||||
onValueChange = { textFieldValue = it },
|
||||
focusRequester = requester
|
||||
)
|
||||
},
|
||||
content = {
|
||||
SearchVideoContent(
|
||||
component,
|
||||
it,
|
||||
requester
|
||||
) { textFieldValue = it }
|
||||
},
|
||||
route = route,
|
||||
scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(),
|
||||
onNavigate = onNavigate
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
@@ -103,7 +141,7 @@ fun SearchVideoContent(
|
||||
Text(
|
||||
text = stringResource(Res.string.search_empty_now),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
modifier = Modifier.clickable { },
|
||||
modifier = Modifier.focusRequester(focusRequester).clickable {},
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ package ru.shadowsparky.ui
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.calculateEndPadding
|
||||
import androidx.compose.foundation.layout.calculateStartPadding
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeDrawing
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
@@ -29,12 +29,13 @@ import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ru.shadowsparky.ui.nav.Route
|
||||
import ru.shadowsparky.ui.theme.ComponentDefaults
|
||||
import ru.shadowsparky.ui.theme.getColorScheme
|
||||
|
||||
const val USE_EXPERIMENTAL_RAIL = false
|
||||
const val USE_EXPERIMENTAL_RAIL = true
|
||||
|
||||
@Immutable
|
||||
data class NavigationEntry<out T : Route>(
|
||||
@@ -125,9 +126,7 @@ private fun <T : Route> BottomBar(
|
||||
NavigationBarItem(
|
||||
currentRoute == entry.route,
|
||||
onClick = { onSelectNavigation?.invoke(entry.route) },
|
||||
icon = {
|
||||
Icon(entry.painter, contentDescription = entry.title)
|
||||
},
|
||||
icon = { Icon(entry.painter, contentDescription = entry.title) },
|
||||
label = { Text(entry.title) }
|
||||
)
|
||||
}
|
||||
@@ -144,23 +143,30 @@ private fun <T : Route> ExpandedContent(
|
||||
onSelectNavigation: ((T) -> Unit)?,
|
||||
content: @Composable ((PaddingValues) -> Unit)
|
||||
) {
|
||||
Row(Modifier.fillMaxSize().padding(values)) {
|
||||
Spacer(Modifier.width(4.dp))
|
||||
NavigationRail {
|
||||
val topPadding = values.calculateTopPadding()
|
||||
val bottomPadding = values.calculateBottomPadding()
|
||||
val startPadding = values.calculateStartPadding(LayoutDirection.Ltr)
|
||||
val endPadding = values.calculateEndPadding(LayoutDirection.Ltr)
|
||||
Row(modifier = Modifier.fillMaxSize().padding(top = topPadding)) {
|
||||
NavigationRail(modifier = Modifier.padding(horizontal = 4.dp)) {
|
||||
navigationEntries.forEach { entry ->
|
||||
NavigationRailItem(
|
||||
selected = currentRoute == entry.route,
|
||||
onClick = { onSelectNavigation?.invoke(entry.route) },
|
||||
icon = {
|
||||
Icon(entry.painter, contentDescription = entry.title)
|
||||
},
|
||||
icon = { Icon(entry.painter, contentDescription = entry.title) },
|
||||
label = { Text(entry.title) }
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.width(4.dp))
|
||||
Box(Modifier.weight(1f)) {
|
||||
content(PaddingValues(0.dp))
|
||||
Box(modifier = Modifier.weight(1f)) {
|
||||
content(
|
||||
PaddingValues(
|
||||
start = startPadding,
|
||||
top = 0.dp,
|
||||
end = endPadding,
|
||||
bottom = bottomPadding
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user