Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Crane] Use AnimatedContent to transition between content states. #843

Merged
merged 8 commits into from
Jun 20, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@

package androidx.compose.samples.crane.home

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedContentScope
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.core.EaseIn
import androidx.compose.animation.core.EaseInOut
import androidx.compose.animation.core.EaseOut
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.with
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.layout.statusBarsPadding
Expand Down Expand Up @@ -85,7 +96,7 @@ fun CraneHome(
}
}

@OptIn(ExperimentalMaterialApi::class)
@OptIn(ExperimentalMaterialApi::class, ExperimentalAnimationApi::class)
@Composable
fun CraneHomeContent(
widthSize: WindowWidthSizeClass,
Expand Down Expand Up @@ -119,32 +130,52 @@ fun CraneHomeContent(
)
},
frontLayerContent = {
when (tabSelected) {
CraneScreen.Fly -> {
suggestedDestinations?.let { destinations ->
AnimatedContent(
tabSelected,
riggaroo marked this conversation as resolved.
Show resolved Hide resolved
transitionSpec = {
val direction = if (initialState.ordinal < targetState.ordinal)
AnimatedContentScope.SlideDirection.Left else AnimatedContentScope
.SlideDirection.Right

slideIntoContainer(
towards = direction,
animationSpec = tween(600)
) with
slideOutOfContainer(
towards = direction,
animationSpec = tween(600)
) using SizeTransform(clip = false, sizeAnimationSpec = { initialSize, targetSize ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting nit: I'd push SizeTransform into a new line and split out its params into individual rows, just for readability

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using the notion with it can't be split onto a new line as its actually an argument

tween(600, easing = EaseInOut)
})
}
) { targetState ->
when (targetState) {
CraneScreen.Fly -> {
suggestedDestinations?.let { destinations ->
ExploreSection(
widthSize = widthSize,
title = stringResource(R.string.explore_flights_by_destination),
exploreList = destinations,
onItemClicked = onExploreItemClicked
)
}
}
CraneScreen.Sleep -> {
ExploreSection(
widthSize = widthSize,
title = stringResource(R.string.explore_flights_by_destination),
exploreList = destinations,
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
)
}
}
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 @@ -159,7 +190,9 @@ private fun HomeTabBar(
modifier: Modifier = Modifier
) {
CraneTabBar(
modifier = modifier.wrapContentWidth().sizeIn(maxWidth = 500.dp),
modifier = modifier
.wrapContentWidth()
.sizeIn(maxWidth = 500.dp),
onMenuClicked = openDrawer
) { tabBarModifier ->
CraneTabs(
Expand All @@ -171,6 +204,7 @@ private fun HomeTabBar(
}
}

@OptIn(ExperimentalAnimationApi::class)
@Composable
private fun SearchContent(
widthSize: WindowWidthSizeClass,
Expand All @@ -183,36 +217,54 @@ private fun SearchContent(
// Reading datesSelected State from here instead of passing the String from the ViewModel
// to cause a recomposition when the dates change.
val selectedDates = viewModel.calendarState.calendarUiState.value.selectedDatesFormatted

when (tabSelected) {
CraneScreen.Fly -> FlySearchContent(
widthSize = widthSize,
datesSelected = selectedDates,
searchUpdates = FlySearchContentUpdates(
onPeopleChanged = onPeopleChanged,
onToDestinationChanged = { viewModel.toDestinationChanged(it) },
onDateSelectionClicked = onDateSelectionClicked,
onExploreItemClicked = onExploreItemClicked
AnimatedContent(
tabSelected,
riggaroo marked this conversation as resolved.
Show resolved Hide resolved
transitionSpec = {
fadeIn(
animationSpec = tween(600, easing = EaseIn)
).with(
fadeOut(
animationSpec = tween(600, easing = EaseOut)
)
).using(
SizeTransform(
sizeAnimationSpec = { _, _ ->
tween(1000, easing = EaseInOut)
}
)
)
)
CraneScreen.Sleep -> SleepSearchContent(
widthSize = widthSize,
datesSelected = selectedDates,
sleepUpdates = SleepSearchContentUpdates(
onPeopleChanged = onPeopleChanged,
onDateSelectionClicked = onDateSelectionClicked,
onExploreItemClicked = onExploreItemClicked
},
) { targetState ->
when (targetState) {
CraneScreen.Fly -> FlySearchContent(
widthSize = widthSize,
datesSelected = selectedDates,
searchUpdates = FlySearchContentUpdates(
onPeopleChanged = onPeopleChanged,
onToDestinationChanged = { viewModel.toDestinationChanged(it) },
onDateSelectionClicked = onDateSelectionClicked,
onExploreItemClicked = onExploreItemClicked
)
)
)
CraneScreen.Eat -> EatSearchContent(
widthSize = widthSize,
datesSelected = selectedDates,
eatUpdates = EatSearchContentUpdates(
onPeopleChanged = onPeopleChanged,
onDateSelectionClicked = onDateSelectionClicked,
onExploreItemClicked = onExploreItemClicked
CraneScreen.Sleep -> SleepSearchContent(
widthSize = widthSize,
datesSelected = selectedDates,
sleepUpdates = SleepSearchContentUpdates(
onPeopleChanged = onPeopleChanged,
onDateSelectionClicked = onDateSelectionClicked,
onExploreItemClicked = onExploreItemClicked
)
)
)
CraneScreen.Eat -> EatSearchContent(
widthSize = widthSize,
datesSelected = selectedDates,
eatUpdates = EatSearchContentUpdates(
onPeopleChanged = onPeopleChanged,
onDateSelectionClicked = onDateSelectionClicked,
onExploreItemClicked = onExploreItemClicked
)
)
}
}
}

Expand Down