Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
Expand All @@ -31,6 +32,10 @@ import androidx.compose.material3.ListItem
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand Down Expand Up @@ -73,24 +78,41 @@ fun ConversationListScreen(
@Composable
fun ConversationDetailScreen(
conversationDetail: ConversationDetail,
onBack: () -> Unit,
onProfileClicked: () -> Unit
) {
Column(
Box(
modifier = Modifier
.fillMaxSize()
.background(colors[conversationDetail.colorId])
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
.padding(16.dp)
) {
Text(
text = "Conversation Detail Screen: ${conversationDetail.id}",
style = MaterialTheme.typography.headlineMedium,
color = MaterialTheme.colorScheme.onSurface
)
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = onProfileClicked) {
Text("View Profile")
if (LocalBackButtonVisibility.current) {
IconButton(
onClick = onBack,
modifier = Modifier.align(Alignment.TopStart)
) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "Back"
)
}
}
Column(
modifier = Modifier
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "Conversation Detail Screen: ${conversationDetail.id}",
style = MaterialTheme.typography.headlineMedium,
color = MaterialTheme.colorScheme.onSurface
)
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = onProfileClicked) {
Text("View Profile")
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class ListDetailActivity : ComponentActivity() {
) { conversationDetail ->
ConversationDetailScreen(
conversationDetail = conversationDetail,
onBack = { backStack.removeLastOrNull() },
onProfileClicked = { backStack.add(Profile) }
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.navigation3.runtime.NavEntry
Expand Down Expand Up @@ -52,18 +54,22 @@ class ListDetailScene<T : Any>(
Column(modifier = Modifier.weight(0.4f)) {
listEntry.Content()
}
Column(modifier = Modifier.weight(0.6f)) {
AnimatedContent(
targetState = detailEntry,
contentKey = { entry -> entry.contentKey },
transitionSpec = {
slideInHorizontally(
initialOffsetX = { it }
) togetherWith
slideOutHorizontally(targetOffsetX = { -it })

// Let the detail entry know not to display a back button.
CompositionLocalProvider(LocalBackButtonVisibility provides false){
Column(modifier = Modifier.weight(0.6f)) {
AnimatedContent(
targetState = detailEntry,
contentKey = { entry -> entry.contentKey },
transitionSpec = {
slideInHorizontally(
initialOffsetX = { it }
) togetherWith
slideOutHorizontally(targetOffsetX = { -it })
}
) { entry ->
entry.Content()
}
){ entry ->
entry.Content()
}
}
}
Expand All @@ -87,6 +93,13 @@ class ListDetailScene<T : Any>(
}
}

/**
* This `CompositionLocal` can be used by a detail `NavEntry` to decide whether to display
* a back button. Default is `true`. It is set to `false` for a detail `NavEntry` when being
* displayed in a `ListDetailScene`.
*/
val LocalBackButtonVisibility = compositionLocalOf{ true }

@Composable
fun <T : Any> rememberListDetailSceneStrategy(): ListDetailSceneStrategy<T> {
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ A `ListDetailSceneStrategy` will return a `ListDetailScene` if:
- A `Detail` entry is the last item in the back stack
- A `List` entry is in the back stack

The `ListDetailScene` provides a `CompositionLocal` named `LocalBackButtonVisibility` that can be used by the detail `NavEntry` to control whether it displays a back button. This is useful when the detail entry usually displays a back button but should not display it when being displayed in a `ListDetailScene`. See https://github.com/android/nav3-recipes/issues/151 for more details on this use case.

See `ListDetailScene.kt` for more implementation details.