Skip to content

Commit c69b3c0

Browse files
committed
Merge remote-tracking branch 'origin/main'
# Conflicts: # app/src/main/java/com/cavin/material3expressivecatalog/navigation/AppNavigation.kt
2 parents 0729c9d + 423ffb6 commit c69b3c0

File tree

6 files changed

+205
-2
lines changed

6 files changed

+205
-2
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ Explore the app to see these components in action!
108108

109109
## 🗺️ Roadmap
110110

111-
- [ ] Expand component coverage: Integrate all Material 3 expressive components with comprehensive
112-
descriptions and usage guidelines (WIP)
111+
- [X] Expand component coverage: Integrate all Material 3 expressive components with comprehensive
112+
descriptions and usage guidelines
113113
- [ ] Code navigation: Implement direct links from component examples to their corresponding source
114114
code for easier exploration.
115115
- [ ] Overall polish: Conduct a thorough review and refinement of the entire application for
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* Designed and developed by Cavin
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.cavin.material3expressivecatalog.components.widenavigationrail
17+
18+
import android.annotation.SuppressLint
19+
import android.app.Activity
20+
import android.content.pm.ActivityInfo
21+
import androidx.compose.foundation.layout.Column
22+
import androidx.compose.foundation.layout.Row
23+
import androidx.compose.foundation.layout.fillMaxWidth
24+
import androidx.compose.foundation.layout.padding
25+
import androidx.compose.material.icons.Icons
26+
import androidx.compose.material.icons.automirrored.filled.MenuOpen
27+
import androidx.compose.material.icons.filled.Favorite
28+
import androidx.compose.material.icons.filled.Home
29+
import androidx.compose.material.icons.filled.Menu
30+
import androidx.compose.material.icons.filled.Star
31+
import androidx.compose.material.icons.outlined.FavoriteBorder
32+
import androidx.compose.material.icons.outlined.Home
33+
import androidx.compose.material.icons.outlined.StarBorder
34+
import androidx.compose.material3.Icon
35+
import androidx.compose.material3.IconButton
36+
import androidx.compose.material3.Text
37+
import androidx.compose.material3.WideNavigationRail
38+
import androidx.compose.material3.WideNavigationRailItem
39+
import androidx.compose.material3.WideNavigationRailValue
40+
import androidx.compose.material3.rememberWideNavigationRailState
41+
import androidx.compose.runtime.Composable
42+
import androidx.compose.runtime.DisposableEffect
43+
import androidx.compose.runtime.getValue
44+
import androidx.compose.runtime.mutableIntStateOf
45+
import androidx.compose.runtime.remember
46+
import androidx.compose.runtime.rememberCoroutineScope
47+
import androidx.compose.runtime.setValue
48+
import androidx.compose.ui.Modifier
49+
import androidx.compose.ui.platform.LocalContext
50+
import androidx.compose.ui.semantics.semantics
51+
import androidx.compose.ui.semantics.stateDescription
52+
import androidx.compose.ui.unit.dp
53+
import kotlinx.coroutines.launch
54+
55+
@SuppressLint("SourceLockedOrientationActivity")
56+
@Composable
57+
fun WideNavigationRail() {
58+
var selectedItem by remember { mutableIntStateOf(0) }
59+
val items = listOf("Home", "Search", "Settings")
60+
val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Favorite, Icons.Filled.Star)
61+
val unselectedIcons =
62+
listOf(Icons.Outlined.Home, Icons.Outlined.FavoriteBorder, Icons.Outlined.StarBorder)
63+
val state = rememberWideNavigationRailState()
64+
val scope = rememberCoroutineScope()
65+
66+
Row(Modifier.fillMaxWidth()) {
67+
WideNavigationRail(
68+
state = state,
69+
header = {
70+
IconButton(
71+
modifier =
72+
Modifier
73+
.padding(start = 24.dp)
74+
.semantics {
75+
// The button must announce the expanded or collapsed state of the rail
76+
// for accessibility.
77+
stateDescription =
78+
if (state.currentValue == WideNavigationRailValue.Expanded) {
79+
"Expanded"
80+
} else {
81+
"Collapsed"
82+
}
83+
},
84+
onClick = {
85+
scope.launch {
86+
if (state.targetValue == WideNavigationRailValue.Expanded) {
87+
state.collapse()
88+
} else {
89+
state.expand()
90+
}
91+
}
92+
},
93+
) {
94+
if (state.targetValue == WideNavigationRailValue.Expanded) {
95+
Icon(
96+
Icons.AutoMirrored.Filled.MenuOpen,
97+
"Collapse rail",
98+
)
99+
} else {
100+
Icon(Icons.Filled.Menu, "Expand rail")
101+
}
102+
}
103+
},
104+
) {
105+
items.forEachIndexed { index, item ->
106+
WideNavigationRailItem(
107+
railExpanded = state.targetValue == WideNavigationRailValue.Expanded,
108+
icon = {
109+
val imageVector =
110+
if (selectedItem == index) {
111+
selectedIcons[index]
112+
} else {
113+
unselectedIcons[index]
114+
}
115+
Icon(imageVector = imageVector, contentDescription = null)
116+
},
117+
label = { Text(item) },
118+
selected = selectedItem == index,
119+
onClick = { selectedItem = index },
120+
)
121+
}
122+
}
123+
124+
val textString =
125+
if (state.currentValue == WideNavigationRailValue.Expanded) {
126+
"Expanded"
127+
} else {
128+
"Collapsed"
129+
}
130+
Column {
131+
Text(modifier = Modifier.padding(16.dp), text = "Is animating: " + state.isAnimating)
132+
Text(modifier = Modifier.padding(16.dp), text = "The rail is $textString.")
133+
Text(
134+
modifier = Modifier.padding(16.dp),
135+
text =
136+
"Note: The orientation of this demo has been locked to portrait mode, because" +
137+
" landscape mode may result in a compact height in certain devices. For" +
138+
" any compact screen dimensions, use a Navigation Bar instead.",
139+
)
140+
}
141+
}
142+
143+
// Lock the orientation for this demo as the navigation rail may look cut off in landscape in
144+
// smaller screens.
145+
val context = LocalContext.current
146+
DisposableEffect(context) {
147+
(context as? Activity)?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
148+
onDispose {
149+
(context as? Activity)?.requestedOrientation =
150+
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
151+
}
152+
}
153+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Designed and developed by Cavin
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.cavin.material3expressivecatalog.components.widenavigationrail
17+
18+
import androidx.navigation3.runtime.EntryProviderBuilder
19+
import androidx.navigation3.runtime.NavKey
20+
import androidx.navigation3.runtime.entry
21+
import com.cavin.material3expressivecatalog.navigation.WideNavigationRailRoutes
22+
23+
fun EntryProviderBuilder<NavKey>.wideNavigationRailNavGraph() {
24+
entry<WideNavigationRailRoutes.ToolbarRoute> {
25+
WideNavigationRail()
26+
}
27+
}

app/src/main/java/com/cavin/material3expressivecatalog/home/HomeScreen.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import androidx.compose.material.icons.filled.MoreVert
3131
import androidx.compose.material.icons.filled.Navigation
3232
import androidx.compose.material.icons.filled.TouchApp
3333
import androidx.compose.material.icons.filled.Tune
34+
import androidx.compose.material.icons.filled.ViewWeek
3435
import androidx.compose.material3.Scaffold
3536
import androidx.compose.material3.Text
3637
import androidx.compose.material3.TopAppBar
@@ -51,6 +52,7 @@ fun HomeScreen(
5152
onNavigateToNavigationRailRoute: () -> Unit,
5253
onNavigateToSplitButtonRoute: () -> Unit,
5354
onNavigateToVerticalFloatingToolbarRoute: () -> Unit,
55+
onNavigateToWideNavigationRailRoute: () -> Unit,
5456
) {
5557
val homeItems = listOf(
5658
HomeItemData(
@@ -103,6 +105,11 @@ fun HomeScreen(
103105
icon = Icons.Filled.Tune,
104106
onClickAction = onNavigateToVerticalFloatingToolbarRoute,
105107
),
108+
HomeItemData(
109+
title = "Wide Navigation Rail",
110+
icon = Icons.Filled.ViewWeek,
111+
onClickAction = onNavigateToWideNavigationRailRoute,
112+
),
106113
)
107114

108115
Scaffold(

app/src/main/java/com/cavin/material3expressivecatalog/navigation/AppNavigation.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import com.cavin.material3expressivecatalog.components.navigationrail.navigation
3636
import com.cavin.material3expressivecatalog.components.progressindicators.progressIndicatorNavGraph
3737
import com.cavin.material3expressivecatalog.components.splitbutton.splitButtonNavGraph
3838
import com.cavin.material3expressivecatalog.components.verticalfloatingtoolbar.verticalFloatingToolBarNavGraph
39+
import com.cavin.material3expressivecatalog.components.widenavigationrail.wideNavigationRailNavGraph
3940
import com.cavin.material3expressivecatalog.home.HomeScreen
4041

4142
@Composable
@@ -109,6 +110,11 @@ fun AppNavigation() {
109110
VerticalFloatingToolBarRoutes.ToolbarRoute,
110111
)
111112
},
113+
onNavigateToWideNavigationRailRoute = {
114+
backStack.add(
115+
WideNavigationRailRoutes.ToolbarRoute,
116+
)
117+
},
112118
)
113119
}
114120

@@ -131,6 +137,8 @@ fun AppNavigation() {
131137
splitButtonNavGraph(backStack)
132138

133139
verticalFloatingToolBarNavGraph()
140+
141+
wideNavigationRailNavGraph()
134142
},
135143
)
136144
}

app/src/main/java/com/cavin/material3expressivecatalog/navigation/AppRoutes.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,11 @@ sealed interface VerticalFloatingToolBarRoutes :
144144
@Serializable
145145
data object ToolbarRoute : NavKey, VerticalFloatingToolBarRoutes
146146
}
147+
148+
sealed interface WideNavigationRailRoutes :
149+
Routes,
150+
NavKey {
151+
152+
@Serializable
153+
data object ToolbarRoute : NavKey, WideNavigationRailRoutes
154+
}

0 commit comments

Comments
 (0)