Reputation: 21
I have post in this post I have icon for comments when the user click on it, it should open modal bottom sheet but the problem is Bottom navigation bar appears above modal bottom sheet in jetpack compose, I want to hide the bottom navigation when modal bottom sheet is opening, I will explain this in pictures below
this code is for the screen that have bottom navigation bar :
@Composable
fun HomeScreenWidget(homeViewModel: HomeViewModel = hiltViewModel()) {
val systemUiController = rememberSystemUiController()
systemUiController.setSystemBarsColor(
color = BackgroundColor
)
LaunchedEffect(true) {
homeViewModel.getCurrentUser()
}
val getCurrentUserResult by homeViewModel.getCurrentUserResult.collectAsState()
if (getCurrentUserResult is Resource.Loading) {
CircularProgressIndicator()
} else {
when (getCurrentUserResult) {
is Resource.Success -> {
currentUser = getCurrentUserResult.data
}
is Resource.Error -> {
Timber.e(getCurrentUserResult.message)
}
else -> {}
}
}
val navController = rememberNavController()
Scaffold(
floatingActionButton = {
IconButton(
interactionSource = NoRippleInteractionSource(),
modifier = Modifier
.background(FabColor, shape = CircleShape)
.size(65.dp),
onClick = {},
) {
Icon(
painter = painterResource(id = R.drawable.insta_ic),
contentDescription = "Add",
tint = Color.White
)
}
},
isFloatingActionButtonDocked = true,
floatingActionButtonPosition = FabPosition.Center,
bottomBar = {
BottomNavigationView(navController)
},
content = {
Modifier.padding(it)
DestinationsNavHost(
navController = navController,
navGraph = NavGraphs.root,
startRoute = FeedScreenDestination
)
}
)
}
this code is for feeds screen that have posts and modal bottom sheet :
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun FeedScreenWidget(
homeViewModel: HomeViewModel = hiltViewModel(),
navigator: DestinationsNavigator
) {
val systemUiController = rememberSystemUiController()
systemUiController.setSystemBarsColor(
color = BackgroundColor
)
val lazyPagingItems = homeViewModel.followingPostsListPager.collectAsLazyPagingItems()
val lazyColumnState = rememberLazyListState()
var searchText by remember {
mutableStateOf("")
}
val usernameForModalSheet = remember { mutableStateOf("") }
val postIdForModalSheet = remember { mutableStateOf("") }
val isCommentClicked = remember { mutableStateOf(false) }
val modalBottomSheetState =
rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
skipHalfExpanded = true
)
val scope = rememberCoroutineScope()
ModalBottomSheetLayout(
sheetContent = {
ModalBottomSheetContent(
navigator,
usernameForModalSheet,
postIdForModalSheet,
homeViewModel,
isCommentClicked
)
},
modifier = Modifier.fillMaxSize(),
sheetBackgroundColor = BackgroundColor,
sheetState = modalBottomSheetState
) {
Scaffold(
content = {
Modifier.padding(it)
Column(
modifier = Modifier
.background(BackgroundColor)
.padding(15.dp)
.fillMaxSize()
) {
Column(
modifier = Modifier
.background(BackgroundColor)
.fillMaxSize()
) {
ToolBar(modifier = Modifier)
Spacer(modifier = Modifier.height(10.dp))
// StorySection(modifier = Modifier, currentUser)
Spacer(modifier = Modifier.height(15.dp))
ExplorerSection(
modifier = Modifier,
value = searchText
) { searchText = it }
Spacer(modifier = Modifier.height(10.dp))
PostsSection(
modifier = Modifier,
homeViewModel,
modalBottomSheetState,
scope,
usernameForModalSheet,
postIdForModalSheet,
isCommentClicked,
navigator,
lazyPagingItems,
lazyColumnState
)
}
}
}
)
}
}
Upvotes: 1
Views: 4487
Reputation: 1240
This is not due to a bug in your code, but due to a bad component queue.
I also ran into this problem and after trying a lot of ideas, I came to the conclusion that the only possible way to achieve a good display in such a case is to change the order of function.
You need to move ModalBottomSheetLayout
from screens that contain a navigation bar to a root function to get such structure:
@Composable
fun HomeScreenWidget(homeViewModel: HomeViewModel = hiltViewModel()) {
Scaffold(){}
ModalBottomSheetLayout()
}
To achieve this you need to pass data to the ModalBottomSheetLayout
and also show it with some global state object. For example, you can create a variable in this global state object that will store the currently opened ModalBottomSheetLayout
state and show or hide it this way.
For example:
In AppState class:
var openedPopup by mutableStateOf<OpenedPopup?>(null)
private set
fun updateOpenedPopup(popup: OpenedPopup?) { // pass null to hide popup
openedPopup = popup
}
OpenedPopup:
sealed class OpenedPopup {
object SimplePopup : OpenedPopup() // no external data
class ComplicatedPopup(val state: YourPopupDataState) : OpenedPopup()
}
In HomeScreenWidget:
val simpleBSS = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden, skipHalfExpanded = true)
val complBSS = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden, skipHalfExpanded = true)
LaunchedEffect(key1 = state.openedPopup) {
when (state.openedPopup) {
null -> {
simpleBSS.hide()
complBSS.hide()
}
SimplePopup -> simpleBSS.show()
ComplicatedPopup -> complBSS.show()
}
}
LaunchedEffect(Unit) {
snapshotFlow { simpleBSS.currentValue }
.collect { if (it == ModalBottomSheetValue.Hidden) state.updateOpenedPopup(null) }
}
LaunchedEffect(Unit) {
snapshotFlow { complBSS.currentValue }
.collect { if (it == ModalBottomSheetValue.Hidden) state.updateOpenedPopup(null) }
}
// place your ModalBottomSheetLayout here and pass state
// it is better to put each popup into a separate file and function
ModalBottomSheetLayout(sheetState = simpleBSS){}
ModalBottomSheetLayout(sheetState = complBSS){}
With this approach you can now call specific ModalBottomSheetLayout
from anywhere like this:
state.updateOpenedPopup(SimplePopup)
state.updateOpenedPopup(ComplicatedPopup(YourPopupDataState()))
Note that this approach is only needed for screens where you have a navigation panel, if it doesn't then you can use the approach you have now.
Hope this helps
Upvotes: 0