Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix jetpack navigation pop behaviour incorrect animation?

When using the jetpack navigation host component, I'm having an issue with the navigation "Pop Behaviour" using the a different animation than the one I'd like, and I'm not sure how to force a different one.

enter image description here When flowing between screens, I'm trying to get them to "flow from the right to the left" similar to iOS's navigation. However, when I add the pop behaviour so that Fragment 3 goes back directly to Fragment 1, going from Fragment 2 to Fragment 3 has Fragment 2 moving to the right, rather than to the left.

I've reproduced the issue in this repository: https://github.com/AtomicSimon/Android-Replication-Screen-Flow

Here's the simple screen flow I'm using:

Here's the navigation graph XML:


    <fragment
        android:id="@+id/fragment_1"
        android:label="fragment_fragment_1"
        android:name="com.example.android_replication_screen_flow.fragment_1"
        tools:layout="@layout/fragment_fragment_1">
        <action
            android:id="@+id/action_fragment_1_to_fragment_2"
            app:destination="@id/fragment_2"
            app:enterAnim="@anim/slide_in_from_the_right"
            app:exitAnim="@anim/slide_out_to_the_left"
            app:popEnterAnim="@anim/slide_in_from_the_left"
            app:popExitAnim="@anim/slide_out_to_the_right"/>
    </fragment>
    <fragment
        android:id="@+id/fragment_2"
        android:label="fragment_fragment_2"
        android:name="com.example.android_replication_screen_flow.fragment_2"
        tools:layout="@layout/fragment_fragment_2">
        <action
            android:id="@+id/action_fragment_2_to_fragment_3"
            app:destination="@id/fragment_3"
            app:enterAnim="@anim/slide_in_from_the_right"
            app:exitAnim="@anim/slide_out_to_the_left"
            app:popEnterAnim="@anim/slide_in_from_the_left"
            app:popExitAnim="@anim/slide_out_to_the_right"
            app:popUpTo="@+id/fragment_2"
            app:popUpToInclusive="true"/>
    </fragment>
    <fragment
        android:id="@+id/fragment_3"
        android:label="fragment_fragment_3"
        android:name="com.example.android_replication_screen_flow.fragment_3"
        tools:layout="@layout/fragment_fragment_3"/>

I'd like for Fragment 2 to leave the screen towards the left when going from Fragment 2 to Fragment 3 but I can't get it right.

like image 365
Simon Lemoine Avatar asked Jun 04 '19 16:06

Simon Lemoine


People also ask

What is navigation in Android jetpack?

Navigation refers to the interactions that allow users to navigate across, into, and back out from the different pieces of content within your app. Android Jetpack's Navigation component helps you implement navigation, from simple button clicks to more complex patterns, such as app bars and the navigation drawer.


1 Answers

In order to make this work you have to do the following:

i.) remove "popUpTo" from action "@+id/action_fragment_2_to_fragment_3"

ii.) add a new action to fragment_3 which navigates back to fragment_1 and clears the backstack for you

<fragment
    android:id="@+id/fragment_3"
    android:label="fragment_fragment_3"
    android:name="com.example.android_replication_screen_flow.fragment_3"
    tools:layout="@layout/fragment_fragment_3">

    <action
        android:id="@+id/backToFragment_1_action"
        app:destination="@id/fragment_1"
        app:enterAnim="@anim/enter_from_left"
        app:exitAnim="@anim/exit_to_right"
        app:popUpToInclusive="true"
        app:popUpTo="@id/fragment_1" />

</fragment>

iii.) in order to have the same behaviour when the user clicks the back button, you should add OnBackPressedCallback in onCreate() of Fragment_3 and call the "backToFragment_1_action".

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // This callback will only be called when MyFragment is at least Started.
    requireActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
        @Override
        public void handleOnBackPressed() {
            NavHostFragment.findNavController(Fragment_3.this).navigate(R.id. backToFragment_1_action);
        }
    });
}
like image 92
goemic Avatar answered Sep 24 '22 11:09

goemic