From 8ccec334bda49b12c11d1384190457d27ca78961 Mon Sep 17 00:00:00 2001 From: afohrman Date: Fri, 1 Dec 2023 21:49:26 +0000 Subject: [PATCH] [Predictive Transitions] Added predictive transition support for fragments and views to the Material motion library, and enabled it in shared axis fragment transition demo. This allows all MaterialVisibility transitions to be predictive, although each individual transition must be opted-in in order to be predictive/seekable. Resolves https://github.com/material-components/material-components-android/issues/3619 PiperOrigin-RevId: 587108521 --- build.gradle | 2 +- .../TransitionSharedAxisDemoFragment.java | 60 +++++++++++++------ .../transition/MaterialVisibility.java | 6 ++ .../platform/MaterialVisibility.java | 6 ++ 4 files changed, 56 insertions(+), 18 deletions(-) diff --git a/build.gradle b/build.gradle index 8bc13f94c55..6e0794f442a 100644 --- a/build.gradle +++ b/build.gradle @@ -37,7 +37,7 @@ ext { recyclerViewSelection : '1.0.0', resourceInspectionAnnotation : '1.0.1', resourceInspectionProcessor : '1.0.1', - transition : '1.2.0', + transition : '1.5.0-alpha04', vectorDrawable : '1.1.0', viewpager2 : '1.0.0', dynamicanimation : '1.0.0', diff --git a/catalog/java/io/material/catalog/transition/TransitionSharedAxisDemoFragment.java b/catalog/java/io/material/catalog/transition/TransitionSharedAxisDemoFragment.java index bc8f7b1dfbd..6a5a3efd7b6 100644 --- a/catalog/java/io/material/catalog/transition/TransitionSharedAxisDemoFragment.java +++ b/catalog/java/io/material/catalog/transition/TransitionSharedAxisDemoFragment.java @@ -20,13 +20,15 @@ import android.os.Bundle; import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentTransaction; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import androidx.activity.OnBackPressedCallback; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.transition.Transition; +import androidx.transition.TransitionListenerAdapter; import com.google.android.material.transition.MaterialSharedAxis; import io.material.catalog.feature.DemoFragment; @@ -36,14 +38,6 @@ public class TransitionSharedAxisDemoFragment extends DemoFragment { private static final int LAYOUT_RES_ID_START = R.layout.cat_transition_shared_axis_start; private static final int LAYOUT_RES_ID_END = R.layout.cat_transition_shared_axis_end; - private final OnBackPressedCallback onBackPressedCallback = - new OnBackPressedCallback(/* enabled= */ false) { - @Override - public void handleOnBackPressed() { - replaceFragment(LAYOUT_RES_ID_START); - } - }; - private SharedAxisHelper sharedAxisHelper; @Override @@ -58,12 +52,18 @@ public View onCreateDemoView( @Override public void onViewCreated(@NonNull View view, @Nullable Bundle bundle) { sharedAxisHelper = new SharedAxisHelper(view.findViewById(R.id.controls_layout)); - requireActivity().getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback); - replaceFragment(LAYOUT_RES_ID_START); + Fragment fragment = TransitionSimpleLayoutFragment.newInstance(LAYOUT_RES_ID_START); + + requireActivity() + .getSupportFragmentManager() + .beginTransaction() + .replace(R.id.fragment_container, fragment) + .commit(); sharedAxisHelper.setBackButtonOnClickListener(v -> replaceFragment(LAYOUT_RES_ID_START)); sharedAxisHelper.setNextButtonOnClickListener(v -> replaceFragment(LAYOUT_RES_ID_END)); + sharedAxisHelper.updateButtonsEnabled(true); } private void replaceFragment(@LayoutRes int layoutResId) { @@ -73,14 +73,28 @@ private void replaceFragment(@LayoutRes int layoutResId) { // Set the transition as the Fragment's enter transition. This will be used when the fragment // is added to the container and re-used when the fragment is removed from the container. fragment.setEnterTransition(createTransition(entering)); + if (entering) { + fragment.setReturnTransition(createTransition(false)); + } else { + // Pop the backstack if manually transitioning to the start fragment to remove the end + // fragment from the back stack without a back event. + requireActivity().getSupportFragmentManager().popBackStack(); + } + + getFragmentTransaction(fragment, entering).commit(); + } - getChildFragmentManager() - .beginTransaction() - .replace(R.id.fragment_container, fragment) - .commit(); + private FragmentTransaction getFragmentTransaction(@NonNull Fragment fragment, boolean entering) { + return entering + ? getFragmentTransaction(fragment).addToBackStack(/* name= */ null) + : getFragmentTransaction(fragment); + } - sharedAxisHelper.updateButtonsEnabled(!entering); - onBackPressedCallback.setEnabled(entering); + private FragmentTransaction getFragmentTransaction(@NonNull Fragment fragment) { + return requireActivity() + .getSupportFragmentManager() + .beginTransaction() + .replace(R.id.fragment_container, fragment); } private MaterialSharedAxis createTransition(boolean entering) { @@ -92,6 +106,18 @@ private MaterialSharedAxis createTransition(boolean entering) { // Fragment's layout. transition.addTarget(R.id.start_root); transition.addTarget(R.id.end_root); + transition.addListener( + new TransitionListenerAdapter() { + @Override + public void onTransitionStart(@NonNull Transition transition) { + sharedAxisHelper.updateButtonsEnabled(!entering); + } + + @Override + public void onTransitionCancel(@NonNull Transition transition) { + sharedAxisHelper.updateButtonsEnabled(entering); + } + }); return transition; } diff --git a/lib/java/com/google/android/material/transition/MaterialVisibility.java b/lib/java/com/google/android/material/transition/MaterialVisibility.java index 63d3ef07535..7efe8e6da1d 100644 --- a/lib/java/com/google/android/material/transition/MaterialVisibility.java +++ b/lib/java/com/google/android/material/transition/MaterialVisibility.java @@ -176,4 +176,10 @@ int getEasingThemeAttrResId(boolean appearing) { TimeInterpolator getDefaultEasingInterpolator(boolean appearing) { return AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR; } + + // STRIP-FROM-PLATFORM-TRANSITIONS-PACKAGE + @Override // STRIP-FROM-PLATFORM-TRANSITIONS-PACKAGE + public boolean isSeekingSupported() { // STRIP-FROM-PLATFORM-TRANSITIONS-PACKAGE + return true; // STRIP-FROM-PLATFORM-TRANSITIONS-PACKAGE + } // STRIP-FROM-PLATFORM-TRANSITIONS-PACKAGE } diff --git a/lib/java/com/google/android/material/transition/platform/MaterialVisibility.java b/lib/java/com/google/android/material/transition/platform/MaterialVisibility.java index 6c0d8030410..6be4616b9fc 100644 --- a/lib/java/com/google/android/material/transition/platform/MaterialVisibility.java +++ b/lib/java/com/google/android/material/transition/platform/MaterialVisibility.java @@ -181,4 +181,10 @@ int getEasingThemeAttrResId(boolean appearing) { TimeInterpolator getDefaultEasingInterpolator(boolean appearing) { return AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR; } + + + + + + }