简体   繁体   English

带有过渡的 SwiftUI 动画始终显示幻灯片动画

[英]SwiftUI animation with transition always show slide animation

I have sub-navigation inside Listview and trying to achieve leftSlide and rightSlide animation but it always shows default slide animation.我在 Listview 中有子导航并尝试实现 leftSlide 和 rightSlide 动画,但它始终显示默认幻灯片动画。 I even tried to add .transition(.move(edge: . leading)) & .transition(.move(edge: . trailing))我什至尝试添加.transition(.move(edge: . leading)) & .transition(.move(edge: . trailing))

import SwiftUI
import Combine

struct GameTabView: View {
    @State var selectedTab: Int = 0

    init() {
        UITableView.appearance().sectionHeaderTopPadding = 0
    }

    var body: some View {
        listView
            .ignoresSafeArea()
    }

    var listView: some View {
        List {
            Group {
                Color.gray.frame(height: 400)
                sectionView
            }
            .listRowInsets(EdgeInsets())
        }
        .listStyle(.plain)
    }
    var sectionView: some View {
        Section {
            tabContentView
                .transition(.move(edge: . leading)) // NOT WORKING
                .background(Color.blue)
        } header: {
            headerView
        }
    }

    private var headerView: some View {
        ScrollViewReader { proxy in
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 16) {
                    Button {
                        withAnimation {
                            selectedTab = 0
                        }
                    } label: {
                        Text("AAAA")
                            .padding()
                    }
                    Button {
                        withAnimation {
                            selectedTab = 1
                        }
                    } label: {
                        Text("BBBB")
                            .padding()
                    }
                    Button {
                        withAnimation {
                            selectedTab = 2
                        }
                    } label: {
                        Text("BBBB")
                            .padding()
                    }
                }
            }
        }
        .background(Color.green)
    }

    @ViewBuilder private var tabContentView: some View {
        switch selectedTab {
        case 0:
            DummyScreen(title: "FIRST", color: .red)
        case 1:
            DummyScreen(title: "SECOND", color: .green)
        case 2:
            DummyScreen(title: "THIRD", color: .blue)
        default:
            EmptyView()
        }
    }
}

struct DummyScreen: View {
    let title: String
    let color: Color
    var body: some View {
        VStack {
            ForEach(0..<15, id: \.self) { index in
                HStack {
                    Text("#\(index): title \(title)")
                        .foregroundColor(Color.black)
                        .font(.system(size: 30))
                        .padding(.vertical, 20)
                    Spacer()
                }
                .background(Color.yellow)
            }
        }
        .background(color)
    }
}

在此处输入图像描述

Just like Asperi said, you can change to another type of View to make the transition works.正如 Asperi 所说,您可以更改为另一种类型的 View 以使过渡生效。

I tried your code, changed List to VStack with ScrollView inside to wrap around the tabContentView, and the result of the UI showed the same except with a proper animation now, and you don't have to manually adjust the height of your contents since HStack height is dynamic based on your Text() growth.我尝试了您的代码,将 List 更改为 VStack,其中带有 ScrollView 以环绕 tabContentView,UI 的结果显示相同,除了现在有适当的动画,并且您不必手动调整内容的高度,因为 HStack高度是根据您的 Text() 增长而动态变化的。

Edited: header fixed, animation fixed编辑:标题固定,动画固定

import SwiftUI
import SwiftUITrackableScrollView //Added
import Combine

struct GameTabView: View {

@State private var scrollViewContentOffset = CGFloat(0) //Added
@State var selectedTab: Int = 0

init() {
    UITableView.appearance().sectionHeaderTopPadding = 0
}

var body: some View {
    listView
        .ignoresSafeArea()
}

var listView: some View {
    ZStack { //Added
        TrackableScrollView(.vertical, showIndicators: true, contentOffset: $scrollViewContentOffset)  {
            VStack {
                Color.gray.frame(height: 400)
                sectionView
            }
        }
        if(scrollViewContentOffset > 400) {
            VStack {
                headerView
                Spacer()
            }
        }
    }
}

var sectionView: some View {
    Section {
        tabContentView
            .transition(.scale) // FIXED
            .background(Color.blue)
    } header: {
        headerView
    }
}

private var headerView: some View {
    ScrollViewReader { proxy in
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 16) {
                Button {
                    withAnimation {
                        selectedTab = 0
                    }
                } label: {
                    Text("AAAA")
                        .padding()
                }
                Button {
                    withAnimation {
                        selectedTab = 1
                    }
                } label: {
                    Text("BBBB")
                        .padding()
                }
                Button {
                    withAnimation {
                        selectedTab = 2
                    }
                } label: {
                    Text("BBBB")
                        .padding()
                }
            }
        }
    }
    .background(Color.green)
}

@ViewBuilder private var tabContentView: some View {
    switch selectedTab {
    case 0:
        DummyScreen(title: "FIRST", color: .red)
    case 1:
        DummyScreen(title: "SECOND", color: .green)
    case 2:
        DummyScreen(title: "THIRD", color: .blue)
    default:
        EmptyView()
    }
}
}

struct DummyScreen: View {
let title: String
let color: Color
var body: some View {
    VStack {
        ForEach(0..<15, id: \.self) { index in
            HStack {
                Text("#\(index): title \(title)")
                    .foregroundColor(Color.black)
                    .font(.system(size: 30))
                    .padding(.vertical, 20)
                Spacer()
            }
            .background(Color.yellow)
        }
    }
    .background(color)
}
}

Thanks to @tail and @Asperi感谢@tail 和@Asperi

I finally got the solution via updating ScrollView with ScrollviewProxy :我终于通过使用ScrollviewProxy更新ScrollView得到了解决方案:

import SwiftUI
import Combine

struct GameTabView: View {
    @State var selectedTab: Int = 0
    @State var proxy: ScrollViewProxy?

    init() {
        UITableView.appearance().sectionHeaderTopPadding = 0
    }

    var body: some View {
        listView
            .ignoresSafeArea()
    }

    var listView: some View {
        List {
            Group {
                Color.gray.frame(height: 400)
                sectionView
            }
            .listRowInsets(EdgeInsets())
        }
        .listStyle(.plain)
    }
    var sectionView: some View {
        Section {
            tabContentView
        } header: {
            headerView
        }
    }

    private var headerView: some View {
        ScrollViewReader { proxy in
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 16) {
                    Button {
                        withAnimation {
                            selectedTab = 0
                            self.proxy?.scrollTo(0, anchor: .center)
                        }
                    } label: {
                        Text("AAAA")
                            .padding()
                    }
                    Button {
                        withAnimation {
                            selectedTab = 1
                            self.proxy?.scrollTo(1, anchor: .center)
                        }
                    } label: {
                        Text("BBBB")
                            .padding()
                    }
                    Button {
                        withAnimation {
                            selectedTab = 2
                            self.proxy?.scrollTo(2, anchor: .center)
                        }
                    } label: {
                        Text("BBBB")
                            .padding()
                    }
                }
            }
        }
        .background(Color.green)
    }

    @ViewBuilder private var tabContentView: some View {
        ScrollViewReader { proxy in
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 0) {
                    ForEach(0..<3, id: \.self) { i in
                        DummyScreen(title: "Name: \(i)", color: .blue)
                            .frame(idealWidth: UIScreen.main.bounds.width)
                            .id(i)
                    }
                }
            }
            .onAppear {
                self.proxy = proxy
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM