@@ -18,32 +18,37 @@ package androidx.compose.samples.crane.base
1818
1919import androidx.compose.foundation.Image
2020import androidx.compose.foundation.clickable
21+ import androidx.compose.foundation.layout.Arrangement
2122import androidx.compose.foundation.layout.Box
2223import androidx.compose.foundation.layout.Column
2324import androidx.compose.foundation.layout.Row
2425import androidx.compose.foundation.layout.Spacer
2526import androidx.compose.foundation.layout.WindowInsets
27+ import androidx.compose.foundation.layout.aspectRatio
2628import androidx.compose.foundation.layout.fillMaxSize
29+ import androidx.compose.foundation.layout.fillMaxWidth
2730import androidx.compose.foundation.layout.height
2831import androidx.compose.foundation.layout.navigationBars
2932import androidx.compose.foundation.layout.padding
3033import androidx.compose.foundation.layout.size
3134import androidx.compose.foundation.layout.width
3235import androidx.compose.foundation.layout.windowInsetsBottomHeight
33- import androidx.compose.foundation.lazy.LazyColumn
34- import androidx.compose.foundation.lazy.items
36+ import androidx.compose.foundation.layout.wrapContentHeight
37+ import androidx.compose.foundation.lazy.grid.GridCells
38+ import androidx.compose.foundation.lazy.grid.GridItemSpan
39+ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
40+ import androidx.compose.foundation.lazy.grid.items
3541import androidx.compose.foundation.shape.RoundedCornerShape
36- import androidx.compose.material.Divider
3742import androidx.compose.material.MaterialTheme
3843import androidx.compose.material.Surface
3944import androidx.compose.material.Text
45+ import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
4046import androidx.compose.runtime.Composable
4147import androidx.compose.samples.crane.R
4248import androidx.compose.samples.crane.data.ExploreModel
4349import androidx.compose.samples.crane.home.OnExploreItemClicked
4450import androidx.compose.samples.crane.ui.BottomSheetShape
4551import androidx.compose.samples.crane.ui.crane_caption
46- import androidx.compose.samples.crane.ui.crane_divider_color
4752import androidx.compose.ui.Alignment
4853import androidx.compose.ui.Modifier
4954import androidx.compose.ui.graphics.Color
@@ -56,6 +61,7 @@ import coil.compose.rememberImagePainter
5661
5762@Composable
5863fun ExploreSection (
64+ widthSize : WindowWidthSizeClass ,
5965 modifier : Modifier = Modifier ,
6066 title : String ,
6167 exploreList : List <ExploreModel >,
@@ -68,74 +74,104 @@ fun ExploreSection(
6874 style = MaterialTheme .typography.caption.copy(color = crane_caption)
6975 )
7076 Spacer (Modifier .height(8 .dp))
71- LazyColumn (
72- modifier = Modifier .weight(1f ),
73- ) {
74- items(exploreList) { exploreItem ->
75- Column (Modifier .fillParentMaxWidth()) {
76- ExploreItem (
77- modifier = Modifier .fillParentMaxWidth(),
78- item = exploreItem,
79- onItemClicked = onItemClicked
77+
78+ LazyVerticalGrid (
79+ columns = GridCells .Adaptive (200 .dp),
80+ modifier = Modifier .fillMaxWidth(),
81+ horizontalArrangement = Arrangement .spacedBy(8 .dp),
82+ content = {
83+ items(exploreList) { exploreItem ->
84+ when (widthSize) {
85+ WindowWidthSizeClass .Medium , WindowWidthSizeClass .Expanded -> {
86+ ExploreItemColumn (
87+ modifier = Modifier .fillMaxWidth(),
88+ item = exploreItem,
89+ onItemClicked = onItemClicked
90+ )
91+ }
92+ else -> {
93+ ExploreItemRow (
94+ modifier = Modifier .fillMaxWidth(),
95+ item = exploreItem,
96+ onItemClicked = onItemClicked
97+ )
98+ }
99+ }
100+ }
101+ item(span = {
102+ // Span the whole bottom row of grid items to add space at the bottom of the grid.
103+ GridItemSpan (maxLineSpan)
104+ }) {
105+ Spacer (
106+ modifier = Modifier .windowInsetsBottomHeight(WindowInsets .navigationBars)
80107 )
81- Divider (color = crane_divider_color)
82108 }
83109 }
84- item {
85- Spacer (
86- modifier = Modifier .windowInsetsBottomHeight(WindowInsets .navigationBars)
87- )
88- }
89- }
110+ )
90111 }
91112 }
92113}
93114
115+ /* *
116+ * Composable with large image card and text underneath.
117+ */
94118@OptIn(ExperimentalCoilApi ::class )
95119@Composable
96- private fun ExploreItem (
120+ private fun ExploreItemColumn (
97121 modifier : Modifier = Modifier ,
98122 item : ExploreModel ,
99123 onItemClicked : OnExploreItemClicked
100124) {
101- Row (
125+ Column (
102126 modifier = modifier
103127 .clickable { onItemClicked(item) }
104128 .padding(top = 12 .dp, bottom = 12 .dp)
105129 ) {
106- ExploreImageContainer {
107- Box {
108- val painter = rememberImagePainter(
109- data = item.imageUrl,
110- builder = {
111- crossfade(true )
112- }
113- )
114- Image (
115- painter = painter,
116- contentDescription = null ,
117- contentScale = ContentScale .Crop ,
118- modifier = Modifier .fillMaxSize(),
119- )
130+ ExploreImageContainer (modifier = Modifier .fillMaxWidth()) {
131+ ExploreImage (item)
132+ }
133+ Spacer (Modifier .height(8 .dp))
134+ Column (
135+ modifier = Modifier
136+ .fillMaxWidth()
137+ .wrapContentHeight()
138+ ) {
139+ Text (
140+ modifier = Modifier .fillMaxWidth(),
141+ text = item.city.nameToDisplay,
142+ style = MaterialTheme .typography.subtitle1
143+ )
144+ Spacer (Modifier .height(4 .dp))
145+ Text (
146+ modifier = Modifier .fillMaxWidth(),
147+ text = item.description,
148+ style = MaterialTheme .typography.caption.copy(color = crane_caption)
149+ )
150+ }
151+ }
152+ }
120153
121- if (painter.state is Loading ) {
122- Image (
123- painter = painterResource(id = R .drawable.ic_crane_logo),
124- contentDescription = null ,
125- modifier = Modifier
126- .size(36 .dp)
127- .align(Alignment .Center ),
128- )
129- }
130- }
154+ @Composable
155+ private fun ExploreItemRow (
156+ modifier : Modifier = Modifier ,
157+ item : ExploreModel ,
158+ onItemClicked : OnExploreItemClicked
159+ ) {
160+ Row (
161+ modifier = modifier
162+ .clickable { onItemClicked(item) }
163+ .padding(top = 12 .dp, bottom = 12 .dp)
164+ ) {
165+ ExploreImageContainer (modifier = Modifier .size(64 .dp)) {
166+ ExploreImage (item)
131167 }
132168 Spacer (Modifier .width(24 .dp))
133- Column {
169+ Column (modifier = Modifier .fillMaxWidth()) {
134170 Text (
135171 text = item.city.nameToDisplay,
136172 style = MaterialTheme .typography.h6
137173 )
138- Spacer (Modifier .height(8 .dp))
174+ Spacer (Modifier .height(4 .dp))
139175 Text (
140176 text = item.description,
141177 style = MaterialTheme .typography.caption.copy(color = crane_caption)
@@ -144,9 +180,41 @@ private fun ExploreItem(
144180 }
145181}
146182
183+ @OptIn(ExperimentalCoilApi ::class )
147184@Composable
148- private fun ExploreImageContainer (content : @Composable () -> Unit ) {
149- Surface (Modifier .size(width = 60 .dp, height = 60 .dp), RoundedCornerShape (4 .dp)) {
185+ private fun ExploreImage (item : ExploreModel ) {
186+ Box {
187+ val painter = rememberImagePainter(
188+ data = item.imageUrl,
189+ builder = {
190+ crossfade(true )
191+ }
192+ )
193+ Image (
194+ painter = painter,
195+ contentDescription = null ,
196+ contentScale = ContentScale .Crop ,
197+ modifier = Modifier .fillMaxSize(),
198+ )
199+
200+ if (painter.state is Loading ) {
201+ Image (
202+ painter = painterResource(id = R .drawable.ic_crane_logo),
203+ contentDescription = null ,
204+ modifier = Modifier
205+ .size(36 .dp)
206+ .align(Alignment .Center ),
207+ )
208+ }
209+ }
210+ }
211+
212+ @Composable
213+ private fun ExploreImageContainer (
214+ modifier : Modifier = Modifier ,
215+ content : @Composable () -> Unit
216+ ) {
217+ Surface (modifier.aspectRatio(1f ), RoundedCornerShape (4 .dp)) {
150218 content()
151219 }
152220}
0 commit comments