Skip to content

Commit d81546a

Browse files
committed
adaptive UI updates
1 parent 7a0e5cf commit d81546a

File tree

6 files changed

+127
-38
lines changed

6 files changed

+127
-38
lines changed

android-app/src/main/java/dev/johnoreilly/galwaybus/MainActivity.kt

Lines changed: 106 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
@file:OptIn(ExperimentalCoroutinesApi::class)
1+
@file:OptIn(ExperimentalCoroutinesApi::class, ExperimentalMaterial3WindowSizeClassApi::class,
2+
ExperimentalMaterial3Api::class
3+
)
24

35
package dev.johnoreilly.galwaybus
46

@@ -8,7 +10,15 @@ import android.graphics.Color
810
import android.os.Bundle
911
import androidx.activity.ComponentActivity
1012
import androidx.activity.compose.setContent
13+
import androidx.compose.foundation.layout.Row
14+
import androidx.compose.foundation.layout.WindowInsets
15+
import androidx.compose.foundation.layout.WindowInsetsSides
1116
import androidx.compose.foundation.layout.fillMaxSize
17+
import androidx.compose.foundation.layout.only
18+
import androidx.compose.foundation.layout.padding
19+
import androidx.compose.foundation.layout.safeDrawing
20+
import androidx.compose.foundation.layout.safeDrawingPadding
21+
import androidx.compose.foundation.layout.windowInsetsPadding
1222
import androidx.compose.material.BottomNavigation
1323
import androidx.compose.material.BottomNavigationItem
1424
import androidx.compose.material3.Text
@@ -19,17 +29,27 @@ import androidx.compose.material.icons.outlined.DirectionsBike
1929
import androidx.compose.material.icons.outlined.Favorite
2030
import androidx.compose.material.icons.outlined.FavoriteBorder
2131
import androidx.compose.material.icons.outlined.LocationOn
32+
import androidx.compose.material3.ExperimentalMaterial3Api
2233
import androidx.compose.material3.IconToggleButton
2334
import androidx.compose.material3.MaterialTheme
2435
import androidx.compose.material3.NavigationBar
2536
import androidx.compose.material3.NavigationBarItem
37+
import androidx.compose.material3.NavigationRail
38+
import androidx.compose.material3.NavigationRailItem
39+
import androidx.compose.material3.Scaffold
2640
import androidx.compose.material3.Surface
41+
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
42+
import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass
43+
import androidx.compose.material3.windowsizeclass.WindowSizeClass
44+
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
45+
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
2746
import androidx.compose.runtime.*
2847
import androidx.compose.ui.Modifier
2948
import androidx.compose.ui.graphics.vector.ImageVector
3049
import androidx.compose.ui.res.stringResource
3150
import androidx.compose.ui.unit.dp
3251
import androidx.core.view.WindowCompat
52+
import androidx.navigation.NavDestination.Companion.hierarchy
3353
import androidx.navigation.NavHostController
3454
import androidx.navigation.compose.*
3555
import com.surrus.galwaybus.common.model.Location
@@ -68,7 +88,7 @@ class MainActivity : ComponentActivity() {
6888
if (showLandingScreen) {
6989
LandingScreen(galwayBusViewModel, onTimeout = { showLandingScreen = false })
7090
} else {
71-
MainLayout(fineLocation, fusedLocationWrapper, galwayBusViewModel)
91+
MainLayout(calculateWindowSizeClass(this), fineLocation, fusedLocationWrapper, galwayBusViewModel)
7292
}
7393

7494
}
@@ -88,14 +108,18 @@ sealed class Screens(val route: String, val label: String, val selectedIcon: Ima
88108

89109
@SuppressLint("MissingPermission", "UnusedMaterialScaffoldPaddingParameter")
90110
@Composable
91-
fun MainLayout(fineLocation: PermissionState,
111+
fun MainLayout(windowSizeClass: WindowSizeClass,
112+
fineLocation: PermissionState,
92113
fusedLocationWrapper: FusedLocationWrapper,
93114
viewModel: GalwayBusViewModel
94115
) {
95116
val navController = rememberNavController()
96117
val bottomNavigationItems = listOf(Screens.NearbyScreen, Screens.BikeShareScreen, Screens.FavoritesScreen)
97118
val hasLocationPermission by fineLocation.hasPermission.collectAsState()
98-
val bottomBar: @Composable () -> Unit = { GalwayBusBottomNavigation(navController, bottomNavigationItems) }
119+
120+
val shouldShowBottomBar = windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact ||
121+
windowSizeClass.heightSizeClass == WindowHeightSizeClass.Compact
122+
99123

100124
if (hasLocationPermission) {
101125
LaunchedEffect(fusedLocationWrapper) {
@@ -106,25 +130,48 @@ fun MainLayout(fineLocation: PermissionState,
106130
viewModel.setLocation(Location(location.latitude, location.longitude))
107131
}
108132

109-
NavHost(navController, startDestination = Screens.NearbyScreen.route) {
110-
composable(Screens.NearbyScreen.route) {
111-
NearestBusStopsScreen(bottomBar, viewModel, navController)
112-
}
113-
composable(Screens.FavoritesScreen.route) {
114-
FavoritesScreen(bottomBar, viewModel, navController)
115-
}
116-
composable(Screens.BusInfoScreen.route) {
117-
BusInfoScreen(viewModel, popBack = { navController.popBackStack() }) { busId ->
118-
navController.navigate(Screens.BusRouteScreen.route + "/$busId")
133+
134+
Scaffold(
135+
containerColor = androidx.compose.ui.graphics.Color.Transparent,
136+
contentColor = MaterialTheme.colorScheme.onBackground,
137+
contentWindowInsets = WindowInsets(0, 0, 0, 0),
138+
bottomBar = {
139+
if (shouldShowBottomBar) {
140+
GalwayBusBottomNavigation(navController, bottomNavigationItems)
119141
}
120142
}
121-
composable(Screens.BusRouteScreen.route+ "/{busId}") { backStackEntry ->
122-
BusRouteScreen(viewModel,
123-
backStackEntry.arguments?.get("busId") as String,
124-
popBack = { navController.popBackStack() })
125-
}
126-
composable(Screens.BikeShareScreen.route) {
127-
BikeShareScreen(bottomBar, viewModel)
143+
) { padding ->
144+
145+
Row(Modifier.fillMaxSize().padding(padding)) {
146+
147+
if (!shouldShowBottomBar) {
148+
GalwayBusNavigationRail(navController, bottomNavigationItems)
149+
}
150+
151+
152+
NavHost(navController, startDestination = Screens.NearbyScreen.route) {
153+
composable(Screens.NearbyScreen.route) {
154+
NearestBusStopsScreen(viewModel, navController)
155+
}
156+
composable(Screens.FavoritesScreen.route) {
157+
FavoritesScreen(viewModel, navController)
158+
}
159+
composable(Screens.BusInfoScreen.route) {
160+
BusInfoScreen(
161+
viewModel,
162+
popBack = { navController.popBackStack() }) { busId ->
163+
navController.navigate(Screens.BusRouteScreen.route + "/$busId")
164+
}
165+
}
166+
composable(Screens.BusRouteScreen.route + "/{busId}") { backStackEntry ->
167+
BusRouteScreen(viewModel,
168+
backStackEntry.arguments?.get("busId") as String,
169+
popBack = { navController.popBackStack() })
170+
}
171+
composable(Screens.BikeShareScreen.route) {
172+
BikeShareScreen(viewModel)
173+
}
174+
}
128175
}
129176
}
130177
} else {
@@ -136,8 +183,7 @@ fun MainLayout(fineLocation: PermissionState,
136183
@Composable
137184
private fun GalwayBusBottomNavigation(navController: NavHostController, items: List<Screens>) {
138185

139-
NavigationBar(
140-
) {
186+
NavigationBar {
141187
val navBackStackEntry by navController.currentBackStackEntryAsState()
142188
val currentRoute = navBackStackEntry?.destination?.route
143189

@@ -149,9 +195,7 @@ private fun GalwayBusBottomNavigation(navController: NavHostController, items: L
149195
} else {
150196
screen.unSelectedIcon
151197
}
152-
icon?.let {
153-
Icon(icon, contentDescription = screen.label)
154-
}
198+
icon?.let { Icon(icon, contentDescription = screen.label) }
155199
},
156200
label = { Text(screen.label) },
157201
selected = currentRoute == screen.route,
@@ -168,6 +212,42 @@ private fun GalwayBusBottomNavigation(navController: NavHostController, items: L
168212
}
169213
}
170214

215+
216+
@Composable
217+
private fun GalwayBusNavigationRail(navController: NavHostController, items: List<Screens>) {
218+
219+
NavigationRail(
220+
//modifier = modifier,
221+
containerColor = androidx.compose.ui.graphics.Color.Transparent,
222+
//contentColor = PeopleInSpaceNavigationDefaults.navigationContentColor(),
223+
) {
224+
val navBackStackEntry by navController.currentBackStackEntryAsState()
225+
val currentRoute = navBackStackEntry?.destination?.route
226+
227+
items.forEach { screen ->
228+
val selected = currentRoute == screen.route
229+
230+
NavigationRailItem(
231+
selected = selected,
232+
onClick = {
233+
if (currentRoute != screen.route) {
234+
navController.navigate(screen.route)
235+
}
236+
},
237+
icon = {
238+
val icon = if (selected) {
239+
screen.selectedIcon
240+
} else {
241+
screen.unSelectedIcon
242+
}
243+
icon?.let { Icon(icon, contentDescription = screen.label) }
244+
}
245+
)
246+
}
247+
}
248+
}
249+
250+
171251
@Composable
172252
fun FavoritesButton(
173253
isFavorite: Boolean,

android-app/src/main/java/dev/johnoreilly/galwaybus/ui/screens/BikeShareScreen.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import androidx.compose.foundation.Image
66
import androidx.compose.foundation.layout.Column
77
import androidx.compose.foundation.layout.Row
88
import androidx.compose.foundation.layout.Spacer
9+
import androidx.compose.foundation.layout.WindowInsets
910
import androidx.compose.foundation.layout.fillMaxWidth
1011
import androidx.compose.foundation.layout.padding
1112
import androidx.compose.foundation.layout.size
@@ -43,7 +44,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
4344

4445
@OptIn(ExperimentalCoroutinesApi::class)
4546
@Composable
46-
fun BikeShareScreen(bottomBar: @Composable () -> Unit, viewModel: GalwayBusViewModel) {
47+
fun BikeShareScreen(viewModel: GalwayBusViewModel) {
4748
val stationsState by viewModel.stations.collectAsState()
4849
val isRefreshing by viewModel.isRefreshing.collectAsState()
4950

@@ -57,7 +58,9 @@ fun BikeShareScreen(bottomBar: @Composable () -> Unit, viewModel: GalwayBusViewM
5758
title = { Text("Galway Bike Share") }
5859
)
5960
},
60-
bottomBar = bottomBar) { paddingValues ->
61+
containerColor = Color.Transparent,
62+
contentWindowInsets = WindowInsets(0, 0, 0, 0)
63+
) { paddingValues ->
6164

6265
SwipeRefresh(
6366
state = rememberSwipeRefreshState(isRefreshing),

android-app/src/main/java/dev/johnoreilly/galwaybus/ui/screens/BusInfoScreen.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import androidx.compose.material.icons.filled.ArrowBack
1010
import androidx.compose.runtime.*
1111
import androidx.compose.ui.Alignment
1212
import androidx.compose.ui.Modifier
13+
import androidx.compose.ui.graphics.Color
1314
import androidx.compose.ui.platform.LocalContext
1415
import com.google.android.gms.maps.CameraUpdateFactory
1516
import com.google.android.gms.maps.model.LatLng
@@ -37,8 +38,10 @@ fun BusInfoScreen(viewModel: GalwayBusViewModel,
3738
Icon(Icons.Filled.ArrowBack, contentDescription = "Back")
3839
}
3940
}
40-
)
41-
}) { paddingValues ->
41+
)},
42+
containerColor = Color.Transparent,
43+
contentWindowInsets = WindowInsets(0, 0, 0, 0)
44+
) { paddingValues ->
4245

4346
Column(Modifier.padding(paddingValues)) {
4447
currentBusStop.value?.let { stop ->

android-app/src/main/java/dev/johnoreilly/galwaybus/ui/screens/BusRouteScreen.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import androidx.compose.material.icons.Icons
1010
import androidx.compose.material.icons.filled.ArrowBack
1111
import androidx.compose.runtime.*
1212
import androidx.compose.ui.Modifier
13+
import androidx.compose.ui.graphics.Color
1314
import androidx.compose.ui.unit.dp
1415
import com.pushpal.jetlime.data.JetLimeItemsModel
1516
import com.pushpal.jetlime.data.config.*
@@ -31,7 +32,9 @@ fun BusRouteScreen(viewModel: GalwayBusViewModel, busId: String, popBack: () ->
3132
}
3233
}
3334
)
34-
}
35+
},
36+
containerColor = Color.Transparent,
37+
contentWindowInsets = WindowInsets(0, 0, 0, 0)
3538
) { paddingValues ->
3639

3740
Column(Modifier.padding(paddingValues)) {

android-app/src/main/java/dev/johnoreilly/galwaybus/ui/screens/FavoritesScreen.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
package dev.johnoreilly.galwaybus.ui.screens
44

5+
import androidx.compose.foundation.layout.WindowInsets
56
import androidx.compose.foundation.layout.padding
67
import androidx.compose.material.ExperimentalMaterialApi
78
import androidx.compose.material.ModalBottomSheetLayout
@@ -30,7 +31,7 @@ import dev.johnoreilly.galwaybus.ui.viewmodel.GalwayBusViewModel
3031
import kotlinx.coroutines.launch
3132

3233
@Composable
33-
fun FavoritesScreen(bottomBar: @Composable () -> Unit, viewModel: GalwayBusViewModel, navController: NavHostController) {
34+
fun FavoritesScreen(viewModel: GalwayBusViewModel, navController: NavHostController) {
3435
val favorites by viewModel.favorites.collectAsState()
3536
val busStopList by viewModel.favoriteBusStopList.collectAsState()
3637
val coroutineScope = rememberCoroutineScope()
@@ -43,7 +44,8 @@ fun FavoritesScreen(bottomBar: @Composable () -> Unit, viewModel: GalwayBusViewM
4344
title = { androidx.compose.material3.Text("Galway Bus - Favourites") }
4445
)
4546
},
46-
bottomBar = bottomBar
47+
containerColor = Color.Transparent,
48+
contentWindowInsets = WindowInsets(0, 0, 0, 0)
4749
) {
4850

4951

android-app/src/main/java/dev/johnoreilly/galwaybus/ui/screens/NearbyBusStopsScreen.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ import kotlinx.coroutines.launch
5252
@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterialApi::class)
5353
@SuppressLint("MissingPermission")
5454
@Composable
55-
fun NearestBusStopsScreen(bottomBar: @Composable () -> Unit, viewModel: GalwayBusViewModel, navController: NavHostController) {
55+
fun NearestBusStopsScreen(viewModel: GalwayBusViewModel, navController: NavHostController) {
5656
val coroutineScope = rememberCoroutineScope()
5757
val snackbarHostState = remember { SnackbarHostState() }
5858
val busStopState = viewModel.busStopListState.collectAsState(UiState.Loading)
@@ -71,13 +71,11 @@ fun NearestBusStopsScreen(bottomBar: @Composable () -> Unit, viewModel: GalwayBu
7171
Icon(Icons.Filled.Home, contentDescription = "Center in Eyre Square")
7272
}
7373
}
74-
7574
)
7675
},
7776
containerColor = Color.Transparent,
78-
contentWindowInsets = WindowInsets(0, 0, 0, 0),
79-
bottomBar = bottomBar)
80-
{
77+
contentWindowInsets = WindowInsets(0, 0, 0, 0)
78+
) {
8179

8280
ModalBottomSheetLayout(modifier = Modifier.padding(it), sheetState = sheetState, sheetContent = {
8381
DeparturesSheetContent(viewModel) {

0 commit comments

Comments
 (0)