ナビゲーショングラフで定義されているナビゲーションアクションの例:
<action
Android: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に匹敵)。
どうすればFragment1
表示中Fragment2
スライドして表示されますか?
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>
私自身の場合、最も簡単な解決策は、適切なアニメーションとスタイルで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>
Java:
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);
}
}
新しいフラグメントのスライドアニメーション中に古いフラグメントが消えないようにするには、最初にスライドアニメーションの継続時間のみで構成される空のアニメーションを作成します。 @anim/stationary
と呼びます:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:duration="@slidingAnimationDuration" />
次に、ナビゲーショングラフで、アクションの終了アニメーションを新しく作成した空のアニメーションに設定します。
<fragment Android:id="@+id/oldFragment"
Android:name="OldFragment">
<action Android:id="@+id/action_oldFragment_to_newFragment"
app:destination="@id/newFragment"
app:enterAnim="@anim/sliding"
app:exitAnim="@anim/stationary"
</fragment>
終了アニメーションは古いフラグメントに適用されるため、アニメーションの全期間にわたって古いフラグメントが表示されます。
古いフラグメントが消える理由についての私の推測は、exitアニメーションを指定しない場合、Enterアニメーションが始まると古いフラグメントはデフォルトですぐに削除されます。