summaryrefslogtreecommitdiff
path: root/Source/Android
diff options
context:
space:
mode:
authorTom Pratt <tom.pratt@outlook.com>2026-05-11 07:33:16 -0700
committerTom Pratt <tompratt@squareup.com>2026-07-13 12:34:06 +0200
commit009a87de59951bc4a4484d379f77cf9ed64e04d2 (patch)
tree0cb7b33d12971f46266ab74763d2114f2b6e760e /Source/Android
parentcdaf67c6ce4b5a23c3dd759a439d2bf434396791 (diff)
Scaffold / Appbar composable
Custom composable that switched between compact and medium size app bar depending on a combination of orientation and screen size. (Small app bar when horizontal on small devices, medium app bar otherwise. Medium app bar supports collapse on scroll.
Diffstat (limited to 'Source/Android')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt42
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplaySetupScreen.kt25
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt46
3 files changed, 79 insertions, 34 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt
index d3a05d3fcf..789a3cef17 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt
@@ -4,6 +4,7 @@ package org.dolphinemu.dolphinemu.features.netplay.ui
import android.content.Intent
import android.content.res.Configuration
+import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -45,6 +46,7 @@ import androidx.compose.material3.Card
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExposedDropdownMenuAnchorType
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.ExtendedFloatingActionButton
@@ -54,11 +56,8 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.MediumTopAppBar
-import androidx.compose.material3.MenuAnchorType
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.OutlinedTextField
-import androidx.compose.material3.Scaffold
import androidx.compose.material3.SheetValue
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
@@ -105,6 +104,7 @@ import org.dolphinemu.dolphinemu.features.netplay.model.Player
import org.dolphinemu.dolphinemu.features.netplay.model.SaveTransferProgress
import org.dolphinemu.dolphinemu.features.netplay.model.TraversalState
import org.dolphinemu.dolphinemu.model.GameFile
+import org.dolphinemu.dolphinemu.ui.theme.DolphinScaffold
import org.dolphinemu.dolphinemu.ui.theme.DolphinTheme
import org.dolphinemu.dolphinemu.ui.theme.MenuSpacer
import org.dolphinemu.dolphinemu.ui.theme.OutlinedBox
@@ -142,19 +142,19 @@ fun NetplayScreen(
gameDigestProgress: GameDigestProgress?,
joinAddresses: Map<JoinInfoType, JoinAddress>,
) {
- Scaffold(
- topBar = {
- MediumTopAppBar(
- title = { Text(stringResource(R.string.netplay_title)) },
- navigationIcon = {
- IconButton(onClick = onBackClicked) {
- Icon(
- imageVector = Icons.AutoMirrored.Filled.ArrowBack,
- contentDescription = "Back",
- )
- }
- },
- )
+ val scrollState = rememberScrollState()
+
+ DolphinScaffold(
+ title = {
+ Text(stringResource(R.string.netplay_title))
+ },
+ navigationIcon = {
+ IconButton(onClick = onBackClicked) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+ contentDescription = "Back",
+ )
+ }
},
floatingActionButton = {
if (isHosting) {
@@ -204,6 +204,7 @@ fun NetplayScreen(
joinAddresses = joinAddresses,
selectedJoinInfoType = selectedJoinInfoType,
onSelectedJoinInfoTypeChanged = { selectedJoinInfoType = it },
+ scrollState = scrollState,
contentPadding = innerPadding,
modifier = modifier
)
@@ -230,6 +231,7 @@ fun NetplayScreen(
joinAddresses = joinAddresses,
selectedJoinInfoType = selectedJoinInfoType,
onSelectedJoinInfoTypeChanged = { selectedJoinInfoType = it },
+ scrollState = scrollState,
contentPadding = innerPadding,
modifier = modifier
)
@@ -348,12 +350,13 @@ private fun PortraitContent(
joinAddresses: Map<JoinInfoType, JoinAddress>,
selectedJoinInfoType: JoinInfoType,
onSelectedJoinInfoTypeChanged: (JoinInfoType) -> Unit,
+ scrollState: ScrollState,
contentPadding: PaddingValues,
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier
- .verticalScroll(rememberScrollState())
+ .verticalScroll(scrollState)
.padding(contentPadding)
) {
Chat(
@@ -420,6 +423,7 @@ private fun LandscapeContent(
joinAddresses: Map<JoinInfoType, JoinAddress>,
selectedJoinInfoType: JoinInfoType,
onSelectedJoinInfoTypeChanged: (JoinInfoType) -> Unit,
+ scrollState: ScrollState,
contentPadding: PaddingValues,
modifier: Modifier = Modifier,
) {
@@ -847,7 +851,7 @@ private fun JoinInfoDropdown(
label = { Text(stringResource(R.string.netplay_host_address_label)) },
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded) },
modifier = Modifier
- .menuAnchor(MenuAnchorType.PrimaryNotEditable)
+ .menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable)
.fillMaxWidth()
)
@@ -1005,7 +1009,7 @@ private fun NetworkModeDropdown(
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
colors = ExposedDropdownMenuDefaults.outlinedTextFieldColors(),
modifier = Modifier
- .menuAnchor(MenuAnchorType.PrimaryNotEditable)
+ .menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable)
.fillMaxWidth(),
)
ExposedDropdownMenu(
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplaySetupScreen.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplaySetupScreen.kt
index f7f660638d..ae222e8722 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplaySetupScreen.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplaySetupScreen.kt
@@ -30,11 +30,9 @@ import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.MenuAnchorType
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
-import androidx.compose.material3.Scaffold
import androidx.compose.material3.SecondaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
@@ -57,6 +55,7 @@ import kotlinx.coroutines.flow.emptyFlow
import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.features.netplay.model.ConnectionRole
import org.dolphinemu.dolphinemu.features.netplay.model.ConnectionType
+import org.dolphinemu.dolphinemu.ui.theme.DolphinScaffold
import org.dolphinemu.dolphinemu.ui.theme.DolphinTheme
import org.dolphinemu.dolphinemu.ui.theme.MenuSpacer
@@ -88,19 +87,15 @@ fun NetplaySetupScreen(
onHostClicked: () -> Unit,
onConnectClicked: () -> Unit,
) {
- Scaffold(
- topBar = {
- MediumTopAppBar(
- title = { Text(stringResource(R.string.netplay_setup_title)) },
- navigationIcon = {
- IconButton(onClick = onBackClicked) {
- Icon(
- Icons.AutoMirrored.Filled.ArrowBack,
- contentDescription = "Back"
- )
- }
- },
- )
+ DolphinScaffold(
+ title = { Text(stringResource(R.string.netplay_setup_title)) },
+ navigationIcon = {
+ IconButton(onClick = onBackClicked) {
+ Icon(
+ Icons.AutoMirrored.Filled.ArrowBack,
+ contentDescription = "Back"
+ )
+ }
},
floatingActionButton = {
ExtendedFloatingActionButton(
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt
index c142a44d73..4aa7e2055a 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt
@@ -3,6 +3,7 @@
package org.dolphinemu.dolphinemu.ui.theme
import android.content.Context
+import android.content.res.Configuration
import androidx.annotation.AttrRes
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.ScrollState
@@ -21,12 +22,16 @@ import androidx.compose.material3.ColorScheme
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
+import androidx.compose.material3.Scaffold
import androidx.compose.material3.SheetState
import androidx.compose.material3.SheetValue
import androidx.compose.material3.SheetValue.Hidden
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
@@ -41,6 +46,8 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.nestedscroll.nestedScroll
+import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.TextStyle
@@ -147,6 +154,45 @@ private fun Context.toDolphinColorScheme(isDark: Boolean): ColorScheme {
}
}
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun DolphinScaffold(
+ title: @Composable () -> Unit,
+ navigationIcon: @Composable () -> Unit,
+ modifier: Modifier = Modifier,
+ floatingActionButton: @Composable () -> Unit = {},
+ content: @Composable (PaddingValues) -> Unit,
+) {
+ val isCompactLandscape = with(LocalConfiguration.current) {
+ orientation == Configuration.ORIENTATION_LANDSCAPE && smallestScreenWidthDp < 600
+ }
+
+ val topAppBarScrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
+
+ Scaffold(
+ modifier = modifier.then(
+ if (isCompactLandscape) Modifier
+ else Modifier.nestedScroll(topAppBarScrollBehavior.nestedScrollConnection)
+ ),
+ topBar = {
+ if (isCompactLandscape) {
+ TopAppBar(
+ title = title,
+ navigationIcon = navigationIcon,
+ )
+ } else {
+ MediumTopAppBar(
+ title = title,
+ navigationIcon = navigationIcon,
+ scrollBehavior = topAppBarScrollBehavior,
+ )
+ }
+ },
+ floatingActionButton = floatingActionButton,
+ content = content,
+ )
+}
+
@Composable
fun MenuSpacer() = Spacer(modifier = Modifier.height(16.dp))