Site icon AppTractor

Создаем анимированные переходы с помощью Matched Geometry Effect в SwiftUI

В SwiftUI мы можем создавать плавные переходы между экранами, из одного состояния в другое, с помощью Matched Geometry Effect (эффект совпадающей геометрии). Используя уникальные идентификаторы, мы можем смешивать геометрию двух видов с одним и тем же идентификатором, создавая анимированный переход. Подобные переходы могут быть полезны для навигации или изменения состояния элементов пользовательского интерфейса.

Пример анимации, которую можно получить с помощью эффекта Matched Geometry Effect — App Store от Apple.

Чтобы реализовать его в пользовательском интерфейсе, необходимо:

Давайте добавим анимированный переход с использованием эффекта совпадающей геометрии к следующему виду:

struct AnimatedExampleView: View {
    // Variable to trigger the animated transition
    @State var isExpanded: Bool = true
    
    var body: some View {
        VStack {
            if isExpanded {
                smallSizeView()
            } else {
                largeSizeView()
            }
        }
        .padding()
        // On tap the transition is triggered
        .onTapGesture {
            withAnimation {
                isExpanded.toggle()
            }
        }
    }
    
    @ViewBuilder
    func smallSizeView() -> some View {
        // Initial state of the view
        RoundedRectangle(cornerRadius: 25)
            .fill(.black)
            .frame(width: 300,height: 300)
            .overlay {
                Text("Hello Developer")
                    .font(.headline)
                    .foregroundStyle(.white)
            }
    }
    
    @ViewBuilder
    func largeSizeView() -> some View {
        // Final state of the view
        RoundedRectangle(cornerRadius: 25)
            .fill(.black)
            .overlay {
                Text("Hello Developer")
                    .font(.headline)
                    .foregroundStyle(.white)
            }
    }
    
}

Чтобы включить Matching Geometry Effect, необходимо:

struct AnimatedExampleView: View {
    @State var isExpanded: Bool = true
    
    // Identifier for the rectangle view
    private var rectangleId = "Rectangle"
    
    // Namespace for the expansion effect
    @Namespace var expansionAnimation
    
    var body: some View {
        VStack {
            if isExpanded {
                smallSizeView()
            } else {
                largeSizeView()
            }
        }
        .padding()
        .onTapGesture {
            withAnimation {
                isExpanded.toggle()
            }
        }
    }
    
    @ViewBuilder
    func smallSizeView() -> some View {
        RoundedRectangle(cornerRadius: 25)
            .fill(.black)
            .frame(width: 300,height: 300)
            // Added the matched geometry modifier to the view
            .matchedGeometryEffect(id: rectangleId, in: expansionAnimation)
            .overlay {
                Text("Hello Developer")
                    .font(.headline)
                    .foregroundStyle(.white)
            }
    }
    
    @ViewBuilder
    func largeSizeView() -> some View {
        RoundedRectangle(cornerRadius: 25)
            .fill(.black)
            // Added the matched geometry modifier to the view
            .matchedGeometryEffect(id: rectangleId, in: expansionAnimation)
            .overlay {
                Text("Hello Developer")
                    .font(.headline)
                    .foregroundStyle(.white)
            }
    }
    
}

После этого при запуске анимации представления, имеющие одинаковый идентификатор и находящиеся в одном пространстве имен, будут плавно переходить друг в друга.

Посмотрите еще видео про Matched Geometry Effect:

Источник

Exit mobile version