Skip to content

Commit

Permalink
[Crane] Used material-window to introduce tablet support for Crane
Browse files Browse the repository at this point in the history
Change-Id: I3336c0f3d05b4b657d22efdacecf05f6fdf844e3
  • Loading branch information
riggaroo committed Apr 22, 2022
1 parent 7768a4f commit 0edb192
Show file tree
Hide file tree
Showing 6 changed files with 252 additions and 90 deletions.
1 change: 1 addition & 0 deletions Crane/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ dependencies {
implementation Libs.AndroidX.Compose.runtimeLivedata
implementation Libs.AndroidX.Compose.foundation
implementation Libs.AndroidX.Compose.material
implementation Libs.AndroidX.Compose.materialWindow
implementation Libs.AndroidX.Compose.layout
implementation Libs.AndroidX.Compose.animation
implementation Libs.AndroidX.Compose.toolingPreview
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,37 @@ package androidx.compose.samples.crane.base

import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.windowInsetsBottomHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Divider
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.samples.crane.R
import androidx.compose.samples.crane.data.ExploreModel
import androidx.compose.samples.crane.home.OnExploreItemClicked
import androidx.compose.samples.crane.ui.BottomSheetShape
import androidx.compose.samples.crane.ui.crane_caption
import androidx.compose.samples.crane.ui.crane_divider_color
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
Expand All @@ -56,6 +61,7 @@ import coil.compose.rememberImagePainter

@Composable
fun ExploreSection(
widthSize: WindowWidthSizeClass,
modifier: Modifier = Modifier,
title: String,
exploreList: List<ExploreModel>,
Expand All @@ -68,74 +74,104 @@ fun ExploreSection(
style = MaterialTheme.typography.caption.copy(color = crane_caption)
)
Spacer(Modifier.height(8.dp))
LazyColumn(
modifier = Modifier.weight(1f),
) {
items(exploreList) { exploreItem ->
Column(Modifier.fillParentMaxWidth()) {
ExploreItem(
modifier = Modifier.fillParentMaxWidth(),
item = exploreItem,
onItemClicked = onItemClicked

LazyVerticalGrid(
columns = GridCells.Adaptive(200.dp),
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp),
content = {
items(exploreList) { exploreItem ->
when (widthSize) {
WindowWidthSizeClass.Medium, WindowWidthSizeClass.Expanded -> {
ExploreItemColumn(
modifier = Modifier.fillMaxWidth(),
item = exploreItem,
onItemClicked = onItemClicked
)
}
else -> {
ExploreItemRow(
modifier = Modifier.fillMaxWidth(),
item = exploreItem,
onItemClicked = onItemClicked
)
}
}
}
item(span = {
// Span the whole bottom row of grid items to add space at the bottom of the grid.
GridItemSpan(maxLineSpan)
}) {
Spacer(
modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars)
)
Divider(color = crane_divider_color)
}
}
item {
Spacer(
modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars)
)
}
}
)
}
}
}

/**
* Composable with large image card and text underneath.
*/
@OptIn(ExperimentalCoilApi::class)
@Composable
private fun ExploreItem(
private fun ExploreItemColumn(
modifier: Modifier = Modifier,
item: ExploreModel,
onItemClicked: OnExploreItemClicked
) {
Row(
Column(
modifier = modifier
.clickable { onItemClicked(item) }
.padding(top = 12.dp, bottom = 12.dp)
) {
ExploreImageContainer {
Box {
val painter = rememberImagePainter(
data = item.imageUrl,
builder = {
crossfade(true)
}
)
Image(
painter = painter,
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize(),
)
ExploreImageContainer(modifier = Modifier.fillMaxWidth()) {
ExploreImage(item)
}
Spacer(Modifier.height(8.dp))
Column(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
) {
Text(
modifier = Modifier.fillMaxWidth(),
text = item.city.nameToDisplay,
style = MaterialTheme.typography.subtitle1
)
Spacer(Modifier.height(4.dp))
Text(
modifier = Modifier.fillMaxWidth(),
text = item.description,
style = MaterialTheme.typography.caption.copy(color = crane_caption)
)
}
}
}

if (painter.state is Loading) {
Image(
painter = painterResource(id = R.drawable.ic_crane_logo),
contentDescription = null,
modifier = Modifier
.size(36.dp)
.align(Alignment.Center),
)
}
}
@Composable
private fun ExploreItemRow(
modifier: Modifier = Modifier,
item: ExploreModel,
onItemClicked: OnExploreItemClicked
) {
Row(
modifier = modifier
.clickable { onItemClicked(item) }
.padding(top = 12.dp, bottom = 12.dp)
) {
ExploreImageContainer(modifier = Modifier.size(64.dp)) {
ExploreImage(item)
}
Spacer(Modifier.width(24.dp))
Column {
Column(modifier = Modifier.fillMaxWidth()) {
Text(
text = item.city.nameToDisplay,
style = MaterialTheme.typography.h6
)
Spacer(Modifier.height(8.dp))
Spacer(Modifier.height(4.dp))
Text(
text = item.description,
style = MaterialTheme.typography.caption.copy(color = crane_caption)
Expand All @@ -144,9 +180,41 @@ private fun ExploreItem(
}
}

@OptIn(ExperimentalCoilApi::class)
@Composable
private fun ExploreImageContainer(content: @Composable () -> Unit) {
Surface(Modifier.size(width = 60.dp, height = 60.dp), RoundedCornerShape(4.dp)) {
private fun ExploreImage(item: ExploreModel) {
Box {
val painter = rememberImagePainter(
data = item.imageUrl,
builder = {
crossfade(true)
}
)
Image(
painter = painter,
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize(),
)

if (painter.state is Loading) {
Image(
painter = painterResource(id = R.drawable.ic_crane_logo),
contentDescription = null,
modifier = Modifier
.size(36.dp)
.align(Alignment.Center),
)
}
}
}

@Composable
private fun ExploreImageContainer(
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
Surface(modifier.aspectRatio(1f), RoundedCornerShape(4.dp)) {
content()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
package androidx.compose.samples.crane.home

import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material.BackdropScaffold
import androidx.compose.material.BackdropValue
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Scaffold
import androidx.compose.material.rememberBackdropScaffoldState
import androidx.compose.material.rememberScaffoldState
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
Expand All @@ -40,6 +43,7 @@ import androidx.compose.samples.crane.data.ExploreModel
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import kotlinx.coroutines.launch

Expand All @@ -51,6 +55,7 @@ enum class CraneScreen {

@Composable
fun CraneHome(
widthSize: WindowWidthSizeClass,
onExploreItemClicked: OnExploreItemClicked,
onDateSelectionClicked: () -> Unit,
modifier: Modifier = Modifier,
Expand All @@ -66,6 +71,7 @@ fun CraneHome(
val scope = rememberCoroutineScope()
CraneHomeContent(
modifier = modifier.padding(contentPadding),
widthSize = widthSize,
onExploreItemClicked = onExploreItemClicked,
onDateSelectionClicked = onDateSelectionClicked,
openDrawer = {
Expand All @@ -80,6 +86,7 @@ fun CraneHome(
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun CraneHomeContent(
widthSize: WindowWidthSizeClass,
onExploreItemClicked: OnExploreItemClicked,
onDateSelectionClicked: () -> Unit,
openDrawer: () -> Unit,
Expand All @@ -100,6 +107,7 @@ fun CraneHomeContent(
},
backLayerContent = {
SearchContent(
widthSize,
tabSelected,
viewModel,
onPeopleChanged,
Expand All @@ -112,6 +120,7 @@ fun CraneHomeContent(
CraneScreen.Fly -> {
suggestedDestinations?.let { destinations ->
ExploreSection(
widthSize = widthSize,
title = stringResource(R.string.explore_flights_by_destination),
exploreList = destinations,
onItemClicked = onExploreItemClicked
Expand All @@ -120,13 +129,15 @@ fun CraneHomeContent(
}
CraneScreen.Sleep -> {
ExploreSection(
widthSize = widthSize,
title = stringResource(R.string.explore_properties_by_destination),
exploreList = viewModel.hotels,
onItemClicked = onExploreItemClicked
)
}
CraneScreen.Eat -> {
ExploreSection(
widthSize = widthSize,
title = stringResource(R.string.explore_restaurants_by_destination),
exploreList = viewModel.restaurants,
onItemClicked = onExploreItemClicked
Expand All @@ -145,7 +156,7 @@ private fun HomeTabBar(
modifier: Modifier = Modifier
) {
CraneTabBar(
modifier = modifier,
modifier = modifier.wrapContentWidth().sizeIn(maxWidth = 500.dp),
onMenuClicked = openDrawer
) { tabBarModifier ->
CraneTabs(
Expand All @@ -159,6 +170,7 @@ private fun HomeTabBar(

@Composable
private fun SearchContent(
widthSize: WindowWidthSizeClass,
tabSelected: CraneScreen,
viewModel: MainViewModel,
onPeopleChanged: (Int) -> Unit,
Expand All @@ -171,7 +183,8 @@ private fun SearchContent(

when (tabSelected) {
CraneScreen.Fly -> FlySearchContent(
datesSelected,
widthSize = widthSize,
datesSelected = datesSelected,
searchUpdates = FlySearchContentUpdates(
onPeopleChanged = onPeopleChanged,
onToDestinationChanged = { viewModel.toDestinationChanged(it) },
Expand All @@ -180,15 +193,17 @@ private fun SearchContent(
)
)
CraneScreen.Sleep -> SleepSearchContent(
datesSelected,
widthSize = widthSize,
datesSelected = datesSelected,
sleepUpdates = SleepSearchContentUpdates(
onPeopleChanged = onPeopleChanged,
onDateSelectionClicked = onDateSelectionClicked,
onExploreItemClicked = onExploreItemClicked
)
)
CraneScreen.Eat -> EatSearchContent(
datesSelected,
widthSize = widthSize,
datesSelected = datesSelected,
eatUpdates = EatSearchContentUpdates(
onPeopleChanged = onPeopleChanged,
onDateSelectionClicked = onDateSelectionClicked,
Expand Down
Loading

0 comments on commit 0edb192

Please sign in to comment.