2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FragmentでPredictive backをサポートする

Posted at

Fragment 同士の遷移時アニメーションで Predictive back を有効にする時の実装メモです。
これを書いている時点では、alpha 版のライブラリや Experimental な機能を使用しているため、将来的に変更される可能性があります。

実装

依存関係

ライブラリの依存は以下のバージョン以降である必要があります。

Predictive back の有効

AndroidManifest で Predictive back を有効にします。

AndroidManifest.xml
<!-- Application 全体で有効 -->
<application
    ...
    android:enableOnBackInvokedCallback="true" />

<!-- or Activity 単位で有効 -->
<activity
    ...
    android:enableOnBackInvokedCallback="true" />

次に Fragment で Predictive back を有効にします。
この有効は Application の onCreate もしくは Activity の super.onCreate の前に設定する必要があります。

MainActivity.kt
class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        FragmentManager.enablePredictiveBack(true)
        super.onCreate(savedInstanceState)
        ...
    }
}

遷移アニメーションの実装

Jetpack の Navigation ではデフォルトでは遷移時のアニメーションが入っておらず、Predictive back を有効にしただけでは遷移時のアニメーションや連携は機能しません。
また、Fragment のスタックを独自で管理している場合も Predictive back は機能しないので、Jetpack の Navigation か FragmentManager を使っている必要があります。

パターン 1 : Navigation Component で遷移時アニメーションを設定する

Navigation Component で遷移時のアニメーションを設定するパターンです。

nav_graph.xml
<navigation ...>
    <fragment ...>
        <action
            ...
            app:enterAnim="@animator/nav_default_enter_anim"
            app:exitAnim="@animator/nav_default_exit_anim"
            app:popEnterAnim="@animator/nav_default_pop_enter_anim"
            app:popExitAnim="@animator/nav_default_pop_exit_anim" />
    </fragment> 
</navigation>            

パターン 2 : Transition でアニメーションを設定する

Transition で標準で用意されている AutoTransition を設定して Fragment が表示するときのアニメーションを設定するパターンです。
AutoTransition で適用されるアニメーション自体は Fade になっています。

class FragmentA: Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        exitTransition = AutoTransition()
        reenterTransition = AutoTransition()
    }
}

class FragmentB: Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enterTransition = AutoTransition()
        exitTransition = AutoTransition()
    }
}

material-components の Motion にある Transition 系の API を使っている場合、Predictive back がサポートされているライブラリバージョンを使っているならば追加実装なしで機能します。

パターン 3 : Shared element transition を設定する

Transition を使用する Shared element transition もパターン 2 同様に機能します。
ただし、設定できる Transition に制限があり、Transition の実装クラスで isSeekingSupported = true であるものが Predictive back に対応しています。
また、Shared element trantision の Transition だけでなく、enterTransition のような通常の Transition も設定する必要があります。

// In FragmentA
binding.card.setOnClickListener {
    val extras = FragmentNavigatorExtras(
        it to "shared_element_container",
        binding.icon to "shared_element_icon"
    )
    findNavController().navigate(R.id.action_FragmentA_to_FragmentB, null, null, extras)
}

class FragmentB: Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enterTransition = AutoTransition()
        
        val transition = TransitionSet().apply {
            addTransition(ChangeBounds())
            addTransition(ChangeImageTransform())
        }
        sharedElementEnterTransition = transition
        sharedElementReturnTransition = transition
    }
}

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?