Releases: raamcosta/compose-destinations
1.2.0-beta - Type-safe navigating for result 👀
API CHANGES
- You can now pass arguments back in a type-safe and simple way!
@Destination(style = DestinationStyle.Dialog::class)
@Composable
fun SomeConfirmationDialog(
resultBackNavigator: ResultBackNavigator<Boolean>
) {
// ... after some positive click button:
resultBackNavigator.navigateBack(result = true)
}
@Destination
@Composable
fun OtherScreen(
resultRecipient: ResultRecipient<SomeConfirmationDialogDestination, Boolean>
) {
resultRecipient.onResult { confirmed ->
// called after SomeConfirmationDialog calls `navigateBack` receiving the result passed in
}
}
Read more about it here
FIXES
- Fixed an issue when a specific parameter type of an annotated Composable required opt-in and the
@Optin
was used. The generated Destination was missing that same OptIn.
1.1.6-beta
API Changes
startDestination
of bothDestinationsNavHost
andNavGraph
was renamed tostartRoute
and it's now of typeRoute
(which is an interface only implemented byDestination
andNavGraph
). This is becauseNavGraph
is also a valid starting point for aNavGraph
. So now,Route
is used so that you can pass aDestination
like before or aNavGraph
.RouteIdentified
was renamed toRoute
and is now a sealed interface only implemented byNavGraphSpec
andDestinationSpec
(as seen above).
1.1.5-beta
- Fixes #34
1.1.4-beta - Small fix
Changes
- Fixed #27
1.1.3-beta
Small improvements
-
DestinationsNavigator
received small API changes for clear and pop back stacks. You won't be able to pass aDirection
to these anymore. ADirection
in Compose Destinations is an interface meant only to navigate to a screen since it contains a route with all the arguments. These methods now receive aRouteIdentified
instead which are only implemented by theDestination
andNavGraph
.
With this change, it is now clear in the type system what kind of "route" you pass to each method (yet another reason to use Compose Destinations 🙌 ) -
Documentation updates
-
Compiler error messages for invalid destinations setup improved
-
Fixed a rare issue that could happen when passing a Parcelable argument with a custom @NavTypeSerializer for it.
1.1.2-beta - Internal improvements
Internal improvements
- Fixed issues with vanilla navigation compose string arguments:
- Empty strings
- Strings already encoded for Uri
1.1.1-beta
Parcelable / Serializable navigation arguments improvements
-
Parcelable/Serializable navigation arguments are now queriable from
SavedStateHandle
/NavBackStackEntry
byget<Parcelable>
/getParcelable
respectively (before you could only get them via the generated Destination - this will still be the preferred way since you don't need to use the string keys, but you now have the option). -
You can now optionally define how you want your Parcelable/Serializable navigation arguments to be represented in the navigation route. This enables deep linking into a screen containing a mandatory navigation argument of this type.
Example:
data class Things(
val thingOne: String,
val thingTwo: String
)
@NavTypeSerializer
class ThingsNavTypeSerializer : ParcelableNavTypeSerializer<Things> {
override fun toRouteString(value: Things): String {
return "${value.thingOne};${value.thingTwo}"
}
override fun fromRouteString(routeStr: String, jClass: Class<out Things>): Things {
return routeStr.split(";").run {
Things(get(0), get(1))
}
}
}
Notes:
- After this, you can now use a deep link passing
"thingOne;thingTwo"
in the URL and the instance ofThings
is created from thefromRouteString
method.- Notice the
@NavTypeSerializer
and the superclass you need to implementParcelableNavTypeSerializer<YOUR_NAV_ARG_TYPE>
.
If your navigation argument is Serializable, then your class should implementSerializableNavTypeSerializer<YOUR_NAV_ARG_TYPE>
instead.- Main reason to do this is if you want to have a deep link to this destination sending this parameter. Otherwise, you don't need to do this: Compose Destinations has a default
ParcelableNavTypeSerializer
it will use behind the scenes.
GENERATED CODE PACKAGE
- By default all generated code will be inside a package composed of the common part of all the
@Destination
annotated functions.
For example:
Destination Screen A:
com.yourapp.ui.screens.featureA.ScreenA
Destination Screen B:
com.yourapp.ui.screens.featureB.ScreenB
In this case, the common part would be com.yourapp.ui.screens
, so this would be the base package for the generated code.
- Ability to override the above default with a fixed package name in build.gradle of your module:
ksp {
arg("compose-destinations.codeGenPackageName", "your.preferred.packagename")
}
Note: Regardless of if you go with the default behavior or define your package name, destinations will be in
PACKAGE_NAME.destinations
.
API CHANGES
Routed
interface was renamed toDirection
. This is the instance that gets returned to you when youinvoke
aDestination
. You can then pass it to theDestinationsNavigator
or call.route
to navigate to thisDirection
.
1.0.2-beta
API CHANGES
Parameters accessible when manually calling specific screen Composables
With this version, the way to access parameters inside the trailing lambda has changed.
Now, they are accessible through the receiver of the lambda. This allows lazy evaluation of parameters
and allows us to expose more of them (ex: DestinationsNavigator
) without polluting your code or hurting performance if you don't use them.
It also allowed us to remove APIs like composableWithNoArgs
since now nav args are lazily prepared, and so, there is no reason for these APIs anymore.
Before
composable(SomeScreenDestination) { navArgs, navBackStackEntry ->
SomeScreen(
arg1 = navArgs.arg1,
navigator = DestinationsNavController(navController, navBackStackEntry),
backStackEntry = navBackStackEntry
)
}
After
composable(SomeScreenDestination) { //this: DestinationScope<SomeScreenDestination.NavArgs>
SomeScreen(
arg1 = navArgs.arg1,
navigator = destinationsNavigator,
backStackEntry = navBackStackEntry
)
}
Animations Core
The call to rememberAnimatedNavHostEngine
changed slightly. Mostly related to overriding defaults in nested nav graphs.
Before
val navHostEngine = rememberAnimatedNavHostEngine(
defaultAnimationParams = DefaultAnimationParams(
contentAlignment = Alignment.TopCenter,
), //others are default values which means no animations by default
) { navGraph ->
when(navGraph) {
NavGraphs.settings -> NavGraphDefaultAnimationParams(
enterTransition = { fadeIn(animationSpec = tween(2000)) },
exitTransition = { fadeOut(animationSpec = tween(2000)) }
)
NavGraphs.someOtherGraph -> NavGraphDefaultAnimationParams(
enterTransition = { fadeIn(animationSpec = tween(700)) },
exitTransition = { fadeOut(animationSpec = tween(700)) }
)
else -> NavGraphDefaultAnimationParams()
}
}
After
val navHostEngine = rememberAnimatedNavHostEngine(
navHostContentAlignment = Alignment.TopCenter,
rootDefaultAnimations = RootNavGraphDefaultAnimations(), //default values means no animations by default
defaultAnimationsForNestedNavGraph = mapOf(
NavGraphs.settings to NestedNavGraphDefaultAnimations(
enterTransition = { fadeIn(animationSpec = tween(2000)) },
exitTransition = { fadeOut(animationSpec = tween(2000)) }
),
NavGraphs.otherNestedGraph to NestedNavGraphDefaultAnimations.ACCOMPANIST_FADING
) // all other nav graphs not specified in this map, will get their animations from the `rootDefaultAnimations` above.
)
1.0.0-beta - Usability and internals improved 🙌
NEW FEATURES:
- Support Parcelable, Serializable and Enums navigation arguments 🎉
- Support to disable NavGraphs generation and create your own to have more control on some less common scenarios. This enables multiple
DestinationsNavHost
since you can now declare multiple top-levelNavGraph
s. - Support to manually call specific Destination Composables enabling passing NavHost level components to those specific screens.
- Added extension functions of NavGraphBuilder to make it possible to use original NavHost Composables instead of DestinationsNavHost.
SETUP CHANGES:
- Jetpack Compose Navigation is now a transitive dependency of this library. This means you don't need to add that dependency in your gradle build if you include this library.
- Accompanist Navigation-Animation and Accompanist Navigation-Material are now also transitive dependencies of the "animations-core".
So if you plan to have animated transitions between screens or Bottom Sheet screens, you don't need to include those dependencies.
Simply replace the "normal core" with "animations-core". Check the README setup section.
API CHANGES:
DestinationsNavHost
now has a mandatory parameter:NavGraph
. This is partly due to the feature of disablingNavGraphs
generation (which means we can't always know there is aNavGraph
with the name "root") but also because this is more explicit what navigation graph is being used to populate thatDestinationsNavHost
.- Animations-core contains a
AnimatedNavHostEngine
which you'll need to get callingrememberAnimatedNavHostEngine
and pass toDestinationsNavHost
. TherememberAnimatedNavHostEngine
call accepts aDefaultAnimationParams
for animations that will be applied to all screen transitions (that don't override it) and accepts a lambda that allows you to override the default for specific nested navigation graphs (also overridable by screen viastyle
parameter ofDestination
annotation).
0.9.4-beta
Done
- Changes to accommodate accompanist 0.21.2-beta
API changes
- Due to changes in accompanist navigation animation dependency, we have to define animations in a slightly different way:
BEFORE
object SomeScreenDestinationAnimations : AnimatedDestinationStyle {
override fun AnimatedContentScope<String>.enterTransition(
initial: Destination?,
target: Destination?
): EnterTransition? {
return when (initial) {
SomeOtherScreenDestination ->
slideInHorizontally(
initialOffsetX = { 1000 },
animationSpec = tween(700)
)
else -> null
}
}
//...
AFTER
object SomeScreenDestinationAnimations : DestinationStyle.Animated {
override fun AnimatedContentScope<NavBackStackEntry>.enterTransition(): EnterTransition? {
return when (initialState.navDestination) {
SomeOtherScreenDestination ->
slideInHorizontally(
initialOffsetX = { 1000 },
animationSpec = tween(700)
)
else -> null
}
}
//...
Notes:
- Changed supertype interface from
AnimatedDestinationStyle
toDestinationStyle.Animated
- Methods signature reciver changed to
AnimatedContentScope<NavBackStackEntry>
- Methods signature don't have parameters; you can get the initial and target destinations by
initialState.navDestination
andtargetState.navDestination
- You can check a commit to a file on the sample app where made these changes here
Known compatibility with
- androidx.navigation:navigation-compose:2.4.0-beta02
- androidx.compose.ui:ui:1.1.0-beta02
- com.google.accompanist:accompanist-navigation-material:0.21.2-beta
- com.google.accompanist:accompanist-navigation-animation:0.21.2-beta