Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.d4rk.androidtutorials.java.ui.screens.main;

import android.Manifest;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
Expand Down Expand Up @@ -253,20 +254,6 @@ private void observeViewModel() {
}
}

NavOptions forwardOptions = new NavOptions.Builder()
.setEnterAnim(R.anim.fragment_spring_enter)
.setExitAnim(R.anim.fragment_spring_exit)
.setPopEnterAnim(R.anim.fragment_spring_pop_enter)
.setPopExitAnim(R.anim.fragment_spring_pop_exit)
.build();

NavOptions backwardOptions = new NavOptions.Builder()
.setEnterAnim(R.anim.fragment_spring_pop_enter)
.setExitAnim(R.anim.fragment_spring_pop_exit)
.setPopEnterAnim(R.anim.fragment_spring_enter)
.setPopExitAnim(R.anim.fragment_spring_exit)
.build();

androidx.navigation.NavDestination destination = navController.getCurrentDestination();
if (destination != null) {
currentNavIndex = navOrder.get(destination.getId(), currentNavIndex);
Expand All @@ -281,7 +268,7 @@ private void observeViewModel() {
return true;
}
int newIndex = navOrder.get(item.getItemId());
NavOptions options = newIndex > currentNavIndex ? forwardOptions : backwardOptions;
NavOptions options = applyTopLevelNavAnimations(new NavOptions.Builder()).build();
navController.navigate(item.getItemId(), null, options);
currentNavIndex = newIndex;
return true;
Expand All @@ -295,7 +282,7 @@ private void observeViewModel() {
return true;
}
int newIndex = navOrder.get(item.getItemId());
NavOptions options = newIndex > currentNavIndex ? forwardOptions : backwardOptions;
NavOptions options = applyTopLevelNavAnimations(new NavOptions.Builder()).build();
navController.navigate(item.getItemId(), null, options);
currentNavIndex = newIndex;
return true;
Expand All @@ -316,6 +303,21 @@ private void observeViewModel() {
});
}

private NavOptions.Builder applyTopLevelNavAnimations(NavOptions.Builder builder) {
if (ValueAnimator.areAnimatorsEnabled()) {
builder.setEnterAnim(R.anim.fragment_top_level_enter)
.setExitAnim(R.anim.fragment_top_level_exit)
.setPopEnterAnim(R.anim.fragment_top_level_enter)
.setPopExitAnim(R.anim.fragment_top_level_exit);
} else {
builder.setEnterAnim(0)
Comment on lines +306 to +313

Choose a reason for hiding this comment

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

[P0] Guard ValueAnimator.areAnimatorsEnabled for pre-O devices

applyTopLevelNavAnimations now calls ValueAnimator.areAnimatorsEnabled() unconditionally. That API was added in Android O, but the app’s minSdk is 23, so any device running API 23–25 will crash with NoSuchMethodError as soon as this helper executes (e.g., on app start when navigation is set up). Please gate the call behind a Build.VERSION.SDK_INT >= Build.VERSION_CODES.O check or fall back to querying Settings.Global.ANIMATOR_DURATION_SCALE.

Useful? React with 👍 / 👎.

.setExitAnim(0)
.setPopEnterAnim(0)
.setPopExitAnim(0);
}
return builder;
}


private void navigateToPreferredDestination(int preferredDestination) {
if (navController == null) {
Expand All @@ -328,10 +330,11 @@ private void navigateToPreferredDestination(int preferredDestination) {
lastPreferredStartDestination = preferredDestination;
return;
}
NavOptions options = new NavOptions.Builder()
.setPopUpTo(graph.getStartDestinationId(), true)
.setLaunchSingleTop(true)
.build();
NavOptions options = applyTopLevelNavAnimations(
new NavOptions.Builder()
.setPopUpTo(graph.getStartDestinationId(), true)
.setLaunchSingleTop(true)
).build();
navController.navigate(preferredDestination, null, options);
lastPreferredStartDestination = preferredDestination;
}
Expand Down
13 changes: 0 additions & 13 deletions app/src/main/res/anim/fragment_spring_enter.xml

This file was deleted.

13 changes: 0 additions & 13 deletions app/src/main/res/anim/fragment_spring_exit.xml

This file was deleted.

4 changes: 0 additions & 4 deletions app/src/main/res/anim/fragment_spring_interpolator.xml

This file was deleted.

13 changes: 0 additions & 13 deletions app/src/main/res/anim/fragment_spring_pop_enter.xml

This file was deleted.

13 changes: 0 additions & 13 deletions app/src/main/res/anim/fragment_spring_pop_exit.xml

This file was deleted.

20 changes: 20 additions & 0 deletions app/src/main/res/anim/fragment_top_level_enter.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<scale
android:duration="300"
android:startOffset="90"
android:fromXScale="0.92"
android:fromYScale="0.92"
android:toXScale="1"
android:toYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:interpolator="@android:interpolator/fast_out_extra_slow_in" />
<alpha
Comment on lines +1 to +14

Choose a reason for hiding this comment

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

[P1] Avoid using platform interpolator absent on minSdk

The new fade-through resources reference @android:interpolator/fast_out_extra_slow_in, which was introduced well after API 23. When this animation is inflated on older devices the resource ID is missing and Resources.NotFoundException will be thrown, breaking every top-level navigation transition on those devices. Consider providing a compat interpolator (e.g., via androidx.interpolator or a custom resource packaged in the app) or guard usage by API level.

Useful? React with 👍 / 👎.

android:duration="210"
android:startOffset="90"
android:fromAlpha="0"
android:toAlpha="1"
android:interpolator="@android:interpolator/linear_out_slow_in" />
</set>
9 changes: 9 additions & 0 deletions app/src/main/res/anim/fragment_top_level_exit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<alpha
android:duration="90"
android:fromAlpha="1"
android:toAlpha="0"
android:interpolator="@android:interpolator/fast_out_linear_in" />
</set>
9 changes: 0 additions & 9 deletions app/src/main/res/transition/fragment_spring.xml

This file was deleted.

Loading