Добавьте анимацию при клике из LazyStack

Вопрос или проблема

Добавьте анимацию при клике из LazyStack

Я использую LazyVStack для отображения списка элементов. LazyVStack работает хорошо, но я не могу найти подходящее решение, чтобы открыть детальный вид поверх и сделать пост на полный экран.

LazyVStack определён следующим образом:

struct FeedView: View {
    var body: some View {
        NavigationStack {
            ScrollView {
                LazyVStack(spacing: 8) {
                    ForEach(Post.MOCK_POSTS) { post in
                        FeedPostView(post: post)
                    }
                }
                .padding(.top, 10)
             }
            .navigationTitle("Лента")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Image(systemName: "message")
                        .imageScale(.large)
                }
            }
        }
    }
}

Таким образом, feed выглядит следующим образом:

введите описание изображения здесь

А структура для FeedPostView выглядит следующим образом:

struct FeedPostView: View {
    let post: Post
    
    var body: some View {
        NavigationStack {
            ZStack {
                NavigationLink(destination: PostDetailsView(post: post)) {
                    Image(post.images[0])
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .scaledToFill()
                }
            }
            .frame(maxWidth: .infinity, maxHeight: 450)
            .clipShape(RoundedRectangle(cornerRadius: 15.0))
            .overlay(PostHeaderView(post: post), alignment: .top)
            .overlay(PostCaptionView(post: post), alignment: .bottom)
            .padding([.leading, .trailing])
            .padding(.bottom, 15)
        }
    }
}

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

  • Заголовок медленно перемещается к верхней части экрана.
  • Изображение перемещается ниже заголовка.
  • Затем я добавлю новый раздел ниже.

Я прикрепил ссылку на видео о том, что существует сейчас, но я хочу увидеть переход заголовка от наложения к верхней части экрана, например.

видео

Ответ или решение

Для создания анимации при клике на элемент в LazyVStack, которая позволит отображать детальный экран с эффектом перехода, можно использовать SwiftUI и его возможности анимации. Мы будем реализовывать переход от списка к детальному виду, управляя положением заголовка и изображения во время анимации.

Шаги реализации

  1. Создание состояния для анимации: Мы будем использовать @State для управления состоянием анимации.

  2. Обновление FeedPostView: Изменим FeedPostView, чтобы он реагировал на клик и инициировал анимацию.

  3. Создание PostDetailsView: Это будет экран, на который мы будем переходить с анимацией. Мы добавим анимацию при появлении этого экрана.

Пример кода

import SwiftUI

struct FeedView: View {
    var body: some View {
        NavigationStack {
            ScrollView {
                LazyVStack(spacing: 8) {
                    ForEach(Post.MOCK_POSTS) { post in
                        FeedPostView(post: post)
                    }
                }
                .padding(.top, 10)
            }
            .navigationTitle("Feed")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Image(systemName: "message")
                        .imageScale(.large)
                }
            }
        }
    }
}

struct FeedPostView: View {
    let post: Post
    @State private var isAnimating = false

    var body: some View {
        NavigationLink(destination: PostDetailsView(post: post, isAnimating: $isAnimating)) {
            ZStack {
                Image(post.images[0])
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .scaledToFill()
            }
            .frame(maxWidth: .infinity, maxHeight: 450)
            .clipShape(RoundedRectangle(cornerRadius: 15.0))
            .overlay(PostHeaderView(post: post), alignment: .top)
            .overlay(PostCaptionView(post: post), alignment: .bottom)
            .padding([.leading, .trailing])
            .padding(.bottom, 15)
            .onTapGesture {
                withAnimation(.easeInOut) {
                    isAnimating = true
                }
            }
        }
    }
}

struct PostDetailsView: View {
    let post: Post
    @Binding var isAnimating: Bool

    var body: some View {
        ZStack {
            Color.white.ignoresSafeArea() // Белый фон для детального вида
            VStack(spacing: 0) {
                // Заголовок
                PostHeaderView(post: post)
                    .frame(height: isAnimating ? 100 : 50)
                    .transition(.move(edge: .top))
                    .animation(.easeInOut, value: isAnimating)

                // Изображение
                Image(post.images[0])
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .transition(.move(edge: .top))
                    .animation(.easeInOut, value: isAnimating)

                // Новый раздел под изображением
                Text("Дополнительная информация...")
                    .padding()
            }
            .ignoresSafeArea(edges: .top) // Игнорируем безопасную зону
            .onAppear {
                isAnimating = true
            }
        }
        .navigationBarBackButtonHidden(true) // Скрыть кнопку назад
    }
}

Объяснение кода

  • isAnimating: Этот @State используется для управления состоянием анимации. Когда пользователь нажимает на пост, мы изменяем его состояние, чтобы инициировать анимацию.

  • Переход между экранами: Используя NavigationLink, мы можем легко переходить между экранами. При этом анимация будет происходить при открытии PostDetailsView.

  • Анимация: В PostDetailsView используются модификаторы .transition() и .animation(), чтобы контролировать динамику перехода элементов. Мы меняем высоту заголовка и изображение в зависимости от состояния isAnimating.

Заключение

Данный подход позволяет создать плавную анимацию при переходе от списка постов к детальному просмотру поста. Вы можете изменять параметры анимации, чтобы достичь желаемого визуального результата. Не забудьте протестировать приложение на реальном устройстве, чтобы убедиться в правильности анимации.

Оцените материал
Добавить комментарий

Капча загружается...