Вопрос или проблема
Добавьте анимацию при клике из 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 и его возможности анимации. Мы будем реализовывать переход от списка к детальному виду, управляя положением заголовка и изображения во время анимации.
Шаги реализации
-
Создание состояния для анимации: Мы будем использовать
@State
для управления состоянием анимации. -
Обновление
FeedPostView
: ИзменимFeedPostView
, чтобы он реагировал на клик и инициировал анимацию. - Создание
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
.
Заключение
Данный подход позволяет создать плавную анимацию при переходе от списка постов к детальному просмотру поста. Вы можете изменять параметры анимации, чтобы достичь желаемого визуального результата. Не забудьте протестировать приложение на реальном устройстве, чтобы убедиться в правильности анимации.