Press "Enter" to skip to content

【SwiftUI】matchedGeometryEffect

Swift 2.0 で追加された、シームレスなアニメーションを実装するためのモディファイアです。特定のViewのサイズや位置が変わった時に、以前のサイズ・位置からシームレスにアニメーションしてくれます。

公式ドキュメント: https://developer.apple.com/documentation/swiftui/view/matchedgeometryeffect(id:in:properties:anchor:issource:)

今回は例としてセグメントメニューをタップした時に横にスライドしてアニメーションするメニューを作成しています。

struct SegmentMenu: View {
    @State var currentMenu: String = "メニューA"
    @Namespace var animation
    
    var body: some View {
        let segments = ["メニューA", "メニューB", "メニューC"]
        
        HStack(spacing: 0){
            ForEach(segments, id: \.self) { segment in
                Text(segment)
                    .fontWeight(.semibold)
                    .foregroundColor(currentMenu == segment ? .white : .black)
                    .padding(.vertical, 10)
                    .frame(maxWidth: .infinity)
                    .background {
                        if currentMenu == segment {
                            Capsule()
                                .fill(.black)
                                .matchedGeometryEffect(id: "SEGMENT_MENU", in: animation)
                        }
                    }
                    .contentShape(Capsule())
                    .onTapGesture {
                        withAnimation { currentMenu = segment }
                    }
            }
        }
        .padding()
    }
}

アニメーションさせるViewに対して matchedGeometryEffect を設定します。引数には識別子となる ID(Hashble) と namespace(DynamicProperty)を渡します。namespace の定義の仕方は決まっており、@Namespace をつけてView のインスタンス変数で定義し、body ブロック内でそれを呼び出します。

コメントを残す

メールアドレスが公開されることはありません。