結論
いくつかパターンを試してみたところ、以下のような結果になることがわかりました。
「アニメーション対象のViewをAnyViewで型消去を行なった場合、
そのAnyViewインスタンスに対してなんらかのModifierを指定しない限りアニメーションが効かない。」
実装パターンと挙動の詳細
基本の実装
- 実装の全体はこんな感じです
- 以降はアニメーションの設定をしている箇所のみを抜粋します
struct ContentView: View {
@State private var showsRectangle: Bool = false
var body: some View {
VStack {
if showsRectangle {
// ここから
Rectangle()
.frame(width: 100, height: 100)
.transition(.opacity)
// ここをフォーカス
}
Button(action: {
withAnimation {
self.showsRectangle.toggle()
}
}) {
Text("Button")
}
}
}
}
パターン1
- 通常のtransitionアニメーションを効かせる実装
- アニメーション対象のViewに関して、AnyViewによる型消去なし
// 型消去なし
Rectangle()
.frame(width: 100, height: 100)
.transition(.opacity)
アニメーションが効く ![]()
パターン2
- transitionアニメーションを効かせたいViewを、AnyViewで型消去する実装
- この時、transition modifierは AnyViewに対して実行 する
// 型消去
AnyView(
Rectangle()
.frame(width: 100, height: 100)
).transition(.opacity) // AnyViewに対してtransitionの指定
アニメーションが効く ![]()
パターン3
- transitionアニメーションを効かせたいViewを、AnyViewで型消去する実装
- この時、transition modifierは 型消去される前のViewに対して実行 する
// 型消去
AnyView(
Rectangle()
.frame(width: 100, height: 100)
.transition(.opacity) // 型消去前のViewに対してtransitionの指定
)
アニメーションが効かない ![]()
パターン4
- transitionアニメーションを効かせたいViewを、AnyViewで型消去する実装
- この時、transition modifierは 型消去される前のViewに対して実行 する
- ただし、 AnyViewに対してもなんらかのModifierの指定を行う
// 型消去
AnyView(
Rectangle()
.frame(width: 100, height: 100)
.transition(.opacity) // 型消去前のViewに対してtransitionの指定
).padding() // AnyViewになんらかのModifierを指定
アニメーションが効く ![]()