Browse Source
Add back screen transitions with option to disable them
renovate/androidx.fragment-fragment-ktx-1.x
Add back screen transitions with option to disable them
renovate/androidx.fragment-fragment-ktx-1.x
Ammar Githam
4 years ago
8 changed files with 116 additions and 136 deletions
-
90app/src/main/java/awais/instagrabber/customviews/BarinstaFragmentNavigator.kt
-
14app/src/main/java/awais/instagrabber/customviews/BarinstaNavHostFragment.kt
-
75app/src/main/java/awais/instagrabber/customviews/FragmentNavigatorWithDefaultAnimations.java
-
60app/src/main/java/awais/instagrabber/customviews/NavHostFragmentWithDefaultAnimations.java
-
9app/src/main/java/awais/instagrabber/fragments/settings/GeneralPreferencesFragment.java
-
1app/src/main/java/awais/instagrabber/fragments/settings/PreferenceKeys.kt
-
2app/src/main/res/layout/activity_main.xml
-
1app/src/main/res/values/strings.xml
@ -0,0 +1,90 @@ |
|||||
|
package awais.instagrabber.customviews |
||||
|
|
||||
|
import android.content.Context |
||||
|
import androidx.fragment.app.FragmentManager |
||||
|
import androidx.navigation.NavBackStackEntry |
||||
|
import androidx.navigation.NavOptions |
||||
|
import androidx.navigation.Navigator |
||||
|
import androidx.navigation.fragment.FragmentNavigator |
||||
|
import androidx.navigation.navOptions |
||||
|
import awais.instagrabber.R |
||||
|
import awais.instagrabber.fragments.settings.PreferenceKeys |
||||
|
import awais.instagrabber.utils.Utils |
||||
|
|
||||
|
private val defaultNavOptions = navOptions { |
||||
|
anim { |
||||
|
enter = R.anim.slide_in_right |
||||
|
exit = R.anim.slide_out_left |
||||
|
popEnter = android.R.anim.slide_in_left |
||||
|
popExit = android.R.anim.slide_out_right |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private val emptyNavOptions = navOptions {} |
||||
|
|
||||
|
/** |
||||
|
* Needs to replace FragmentNavigator and replacing is done with name in annotation. |
||||
|
* Navigation method will use defaults for fragments transitions animations. |
||||
|
*/ |
||||
|
@Navigator.Name("fragment") |
||||
|
class BarinstaFragmentNavigator( |
||||
|
context: Context, |
||||
|
fragmentManager: FragmentManager, |
||||
|
containerId: Int |
||||
|
) : FragmentNavigator(context, fragmentManager, containerId) { |
||||
|
|
||||
|
override fun navigate( |
||||
|
entries: List<NavBackStackEntry>, |
||||
|
navOptions: NavOptions?, |
||||
|
navigatorExtras: Navigator.Extras? |
||||
|
) { |
||||
|
val disableTransitions = Utils.settingsHelper.getBoolean(PreferenceKeys.PREF_DISABLE_SCREEN_TRANSITIONS) |
||||
|
if (disableTransitions) { |
||||
|
super.navigate(entries, navOptions, navigatorExtras) |
||||
|
return |
||||
|
} |
||||
|
// this will try to fill in empty animations with defaults when no shared element transitions |
||||
|
// https://developer.android.com/guide/navigation/navigation-animate-transitions#shared-element |
||||
|
val hasSharedElements = navigatorExtras != null && navigatorExtras is Extras |
||||
|
val navOptions1 = if (hasSharedElements) navOptions else navOptions.fillEmptyAnimationsWithDefaults() |
||||
|
super.navigate(entries, navOptions1, navigatorExtras) |
||||
|
} |
||||
|
|
||||
|
private fun NavOptions?.fillEmptyAnimationsWithDefaults(): NavOptions = |
||||
|
this?.copyNavOptionsWithDefaultAnimations() ?: defaultNavOptions |
||||
|
|
||||
|
private fun NavOptions.copyNavOptionsWithDefaultAnimations(): NavOptions = let { originalNavOptions -> |
||||
|
navOptions { |
||||
|
launchSingleTop = originalNavOptions.shouldLaunchSingleTop() |
||||
|
popUpTo(originalNavOptions.popUpToId) { |
||||
|
inclusive = originalNavOptions.isPopUpToInclusive() |
||||
|
saveState = originalNavOptions.shouldPopUpToSaveState() |
||||
|
} |
||||
|
originalNavOptions.popUpToRoute?.let { |
||||
|
popUpTo(it) { |
||||
|
inclusive = originalNavOptions.isPopUpToInclusive() |
||||
|
saveState = originalNavOptions.shouldPopUpToSaveState() |
||||
|
} |
||||
|
} |
||||
|
restoreState = originalNavOptions.shouldRestoreState() |
||||
|
anim { |
||||
|
enter = |
||||
|
if (originalNavOptions.enterAnim == emptyNavOptions.enterAnim) defaultNavOptions.enterAnim |
||||
|
else originalNavOptions.enterAnim |
||||
|
exit = |
||||
|
if (originalNavOptions.exitAnim == emptyNavOptions.exitAnim) defaultNavOptions.exitAnim |
||||
|
else originalNavOptions.exitAnim |
||||
|
popEnter = |
||||
|
if (originalNavOptions.popEnterAnim == emptyNavOptions.popEnterAnim) defaultNavOptions.popEnterAnim |
||||
|
else originalNavOptions.popEnterAnim |
||||
|
popExit = |
||||
|
if (originalNavOptions.popExitAnim == emptyNavOptions.popExitAnim) defaultNavOptions.popExitAnim |
||||
|
else originalNavOptions.popExitAnim |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private companion object { |
||||
|
private const val TAG = "FragmentNavigator" |
||||
|
} |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
package awais.instagrabber.customviews |
||||
|
|
||||
|
import androidx.navigation.NavHostController |
||||
|
import androidx.navigation.fragment.NavHostFragment |
||||
|
|
||||
|
class BarinstaNavHostFragment : NavHostFragment() { |
||||
|
override fun onCreateNavHostController(navHostController: NavHostController) { |
||||
|
super.onCreateNavHostController(navHostController) |
||||
|
navHostController.navigatorProvider.addNavigator( |
||||
|
// this replaces FragmentNavigator |
||||
|
BarinstaFragmentNavigator(requireContext(), childFragmentManager, id) |
||||
|
) |
||||
|
} |
||||
|
} |
@ -1,75 +0,0 @@ |
|||||
package awais.instagrabber.customviews; |
|
||||
|
|
||||
import android.content.Context; |
|
||||
import android.os.Bundle; |
|
||||
|
|
||||
import androidx.annotation.NonNull; |
|
||||
import androidx.annotation.Nullable; |
|
||||
import androidx.fragment.app.FragmentManager; |
|
||||
import androidx.navigation.NavDestination; |
|
||||
import androidx.navigation.NavOptions; |
|
||||
import androidx.navigation.Navigator; |
|
||||
import androidx.navigation.fragment.FragmentNavigator; |
|
||||
|
|
||||
import awais.instagrabber.R; |
|
||||
|
|
||||
@Navigator.Name("fragment") |
|
||||
public class FragmentNavigatorWithDefaultAnimations extends FragmentNavigator { |
|
||||
|
|
||||
private final NavOptions emptyNavOptions = new NavOptions.Builder().build(); |
|
||||
// private final NavOptions defaultNavOptions = new NavOptions.Builder() |
|
||||
// .setEnterAnim(R.animator.nav_default_enter_anim) |
|
||||
// .setExitAnim(R.animator.nav_default_exit_anim) |
|
||||
// .setPopEnterAnim(R.animator.nav_default_pop_enter_anim) |
|
||||
// .setPopExitAnim(R.animator.nav_default_pop_exit_anim) |
|
||||
// .build(); |
|
||||
|
|
||||
private final NavOptions defaultNavOptions = new NavOptions.Builder() |
|
||||
.setEnterAnim(R.anim.slide_in_right) |
|
||||
.setExitAnim(R.anim.slide_out_left) |
|
||||
.setPopEnterAnim(android.R.anim.slide_in_left) |
|
||||
.setPopExitAnim(android.R.anim.slide_out_right) |
|
||||
.build(); |
|
||||
|
|
||||
public FragmentNavigatorWithDefaultAnimations(@NonNull final Context context, |
|
||||
@NonNull final FragmentManager manager, |
|
||||
final int containerId) { |
|
||||
super(context, manager, containerId); |
|
||||
} |
|
||||
|
|
||||
@Nullable |
|
||||
@Override |
|
||||
public NavDestination navigate(@NonNull final Destination destination, |
|
||||
@Nullable final Bundle args, |
|
||||
@Nullable final NavOptions navOptions, |
|
||||
@Nullable final Navigator.Extras navigatorExtras) { |
|
||||
// this will try to fill in empty animations with defaults when no shared element transitions are set |
|
||||
// https://developer.android.com/guide/navigation/navigation-animate-transitions#shared-element |
|
||||
final boolean shouldUseTransitionsInstead = navigatorExtras != null; |
|
||||
final NavOptions navOptions1 = shouldUseTransitionsInstead ? navOptions : fillEmptyAnimationsWithDefaults(navOptions); |
|
||||
return super.navigate(destination, args, navOptions1, navigatorExtras); |
|
||||
} |
|
||||
|
|
||||
private NavOptions fillEmptyAnimationsWithDefaults(@Nullable final NavOptions navOptions) { |
|
||||
if (navOptions == null) { |
|
||||
return defaultNavOptions; |
|
||||
} |
|
||||
return copyNavOptionsWithDefaultAnimations(navOptions); |
|
||||
} |
|
||||
|
|
||||
@NonNull |
|
||||
private NavOptions copyNavOptionsWithDefaultAnimations(@NonNull final NavOptions navOptions) { |
|
||||
return new NavOptions.Builder() |
|
||||
.setLaunchSingleTop(navOptions.shouldLaunchSingleTop()) |
|
||||
.setPopUpTo(navOptions.getPopUpTo(), navOptions.isPopUpToInclusive()) |
|
||||
.setEnterAnim(navOptions.getEnterAnim() == emptyNavOptions.getEnterAnim() |
|
||||
? defaultNavOptions.getEnterAnim() : navOptions.getEnterAnim()) |
|
||||
.setExitAnim(navOptions.getExitAnim() == emptyNavOptions.getExitAnim() |
|
||||
? defaultNavOptions.getExitAnim() : navOptions.getExitAnim()) |
|
||||
.setPopEnterAnim(navOptions.getPopEnterAnim() == emptyNavOptions.getPopEnterAnim() |
|
||||
? defaultNavOptions.getPopEnterAnim() : navOptions.getPopEnterAnim()) |
|
||||
.setPopExitAnim(navOptions.getPopExitAnim() == emptyNavOptions.getPopExitAnim() |
|
||||
? defaultNavOptions.getPopExitAnim() : navOptions.getPopExitAnim()) |
|
||||
.build(); |
|
||||
} |
|
||||
} |
|
@ -1,60 +0,0 @@ |
|||||
// package awais.instagrabber.customviews; |
|
||||
// |
|
||||
// import android.os.Bundle; |
|
||||
// |
|
||||
// import androidx.annotation.NavigationRes; |
|
||||
// import androidx.annotation.NonNull; |
|
||||
// import androidx.annotation.Nullable; |
|
||||
// import androidx.navigation.NavController; |
|
||||
// import androidx.navigation.Navigator; |
|
||||
// import androidx.navigation.fragment.FragmentNavigator; |
|
||||
// import androidx.navigation.fragment.NavHostFragment; |
|
||||
// |
|
||||
// public class NavHostFragmentWithDefaultAnimations extends NavHostFragment { |
|
||||
// private static final String KEY_GRAPH_ID = "android-support-nav:fragment:graphId"; |
|
||||
// private static final String KEY_START_DESTINATION_ARGS = |
|
||||
// "android-support-nav:fragment:startDestinationArgs"; |
|
||||
// private static final String KEY_NAV_CONTROLLER_STATE = |
|
||||
// "android-support-nav:fragment:navControllerState"; |
|
||||
// private static final String KEY_DEFAULT_NAV_HOST = "android-support-nav:fragment:defaultHost"; |
|
||||
// |
|
||||
// @NonNull |
|
||||
// public static NavHostFragment create(@NavigationRes int graphResId) { |
|
||||
// return create(graphResId, null); |
|
||||
// } |
|
||||
// |
|
||||
// @NonNull |
|
||||
// public static NavHostFragment create(@NavigationRes int graphResId, |
|
||||
// @Nullable Bundle startDestinationArgs) { |
|
||||
// Bundle b = null; |
|
||||
// if (graphResId != 0) { |
|
||||
// b = new Bundle(); |
|
||||
// b.putInt(KEY_GRAPH_ID, graphResId); |
|
||||
// } |
|
||||
// if (startDestinationArgs != null) { |
|
||||
// if (b == null) { |
|
||||
// b = new Bundle(); |
|
||||
// } |
|
||||
// b.putBundle(KEY_START_DESTINATION_ARGS, startDestinationArgs); |
|
||||
// } |
|
||||
// |
|
||||
// final NavHostFragmentWithDefaultAnimations result = new NavHostFragmentWithDefaultAnimations(); |
|
||||
// if (b != null) { |
|
||||
// result.setArguments(b); |
|
||||
// } |
|
||||
// return result; |
|
||||
// } |
|
||||
// |
|
||||
// @NonNull |
|
||||
// @Override |
|
||||
// protected Navigator<? extends FragmentNavigator.Destination> createFragmentNavigator() { |
|
||||
// return new FragmentNavigatorWithDefaultAnimations(requireContext(), getChildFragmentManager(), getId()); |
|
||||
// } |
|
||||
// |
|
||||
// @Override |
|
||||
// protected void onCreateNavController(@NonNull final NavController navController) { |
|
||||
// super.onCreateNavController(navController); |
|
||||
// navController.getNavigatorProvider() |
|
||||
// .addNavigator(new FragmentNavigatorWithDefaultAnimations(requireContext(), getChildFragmentManager(), getId())); |
|
||||
// } |
|
||||
// } |
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue