有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何将Android导航架构片段动画化为在旧片段上滑动?

在导航图中定义的导航操作示例中:

<action
    安卓:id="@+id/action_fragment1_to_fragment2"
    app:destination="@id/fragment2"
    app:enterAnim="@anim/right_slide_in"
    app:popExitAnim="@anim/left_slide_out"/>

Fragment2打开并开始从右侧滑入视图时,Fragment1立即消失(可悲)。当Fragment2关闭并开始向右滑动时,Fragment1在其下方清晰可见,提供了很好的堆栈弹出效果(与iOS相当)

Fragment2幻灯片进入视图时,如何保持Fragment1可见


共 (3) 个答案

  1. # 1 楼答案

    编辑: 这不是最优雅的解决方案,它实际上是一个技巧,但它似乎是解决这种情况的最佳方法,直到NavigationComponent包含更好的方法

    因此,我们可以在Fragement2onViewCreated方法中增加translationZ(从API 21开始),使其出现在Fragment1之上

    例如:

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        ViewCompat.setTranslationZ(getView(), 100f);
    }
    

    正如very nice@xinaiz建议的那样,我们可以使用100f或任何其他随机值来为片段指定比前一个更高的高程

    该解决方案由@JFrite在此线程中提出
    FragmentTransaction animation to slide in over top
    更多细节可以在那里找到

  2. # 2 楼答案

    我认为使用R.anim.hold动画会产生你想要的效果:

    int holdingAnimation = R.anim.hold;
    int inAnimation = R.anim.right_slide_in;
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.setCustomAnimations(inAnimation, holdingAnimation, inAnimation, holdingAnimation);
    /*
    ... Add in your fragments and other navigation calls
    */
    transaction.commit();
    getSupportFragmentManager().executePendingTransactions();
    

    或者只是在行动中给它贴上标签

    下面是上面提到的R.anim.hold动画:

    <?xml version="1.0" encoding="utf-8"?>
    <set
        xmlns:android="http://schemas.android.com/apk/res/android">
      <translate
          android:duration="@android:integer/config_longAnimTime"
          android:fromYDelta="0.0%p"
          android:toYDelta="0.0%p"/>
    </set>
    
  3. # 3 楼答案

    在我自己的例子中,最简单的解决方案是使用DialogFragment和适当的动画和风格

    风格:

    <style name="MyDialogAnimation" parent="Animation.AppCompat.Dialog">
            <item name="android:windowEnterAnimation">@anim/slide_in</item>
            <item name="android:windowExitAnimation">@anim/slide_out</item>
    </style>
    
    <style name="MyDialog" parent="ThemeOverlay.MaterialComponents.Light.BottomSheetDialog">
            <item name="android:windowIsFloating">false</item>
            <item name="android:statusBarColor">@color/transparent</item>
            <item name="android:windowAnimationStyle">@style/MyDialogAnimation</item>
    </style>
    

    布局:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:animateLayoutChanges="true"
        android:background="@color/colorWhite"
        android:fillViewport="true"
        android:fitsSystemWindows="true"
        android:layout_gravity="bottom"
        android:orientation="vertical"
        android:scrollbars="none"
        android:transitionGroup="true"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">
    
        <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/root_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            // Your Ui here
    
        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.core.widget.NestedScrollView>
    

    爪哇:

    public class MyFragmentDialog extends DialogFragment {
      @Nullable
      @Override
      public View onCreateView(
          @NonNull LayoutInflater inflater,
          @Nullable ViewGroup container,
          @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_dialog, container, false);
      }
    
      @Override
      public void onStart() {
        super.onStart();
        Dialog dialog = getDialog();
        if (dialog != null) {
          int width = ViewGroup.LayoutParams.MATCH_PARENT;
          int height = ViewGroup.LayoutParams.MATCH_PARENT;
          Objects.requireNonNull(dialog.getWindow())
              .setFlags(
                  WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
                  WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
          Objects.requireNonNull(dialog.getWindow()).setLayout(width, height);
          dialog.getWindow().setWindowAnimations(R.style.MyDialogAnimation);
        }
      }
    
      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(DialogFragment.STYLE_NORMAL, R.style.MyDialog);
      }
    }