NavigationView 奇怪的与子视图之间的转换

Posted

技术标签:

【中文标题】NavigationView 奇怪的与子视图之间的转换【英文标题】:NavigationView odd transition to and from child view 【发布时间】:2021-08-30 11:06:07 【问题描述】:

我希望我可以将我的模拟器记录附加到此请求中。我有一个项目列表,我为它创建了一个 NavigationLink,它根据传入的值调用具有不同数据的子视图。子视图是一个大型水平滚动视图,其页面支持一年中的几个月。 DragGesture 控制水平滚动的位置。

当我从列表过渡到子视图时,它看起来几乎就像从右侧俯冲而入,当它过渡回父列表视图时,您可以看到两个视图的视觉效果在过渡期间短暂出现。

我相信它与 GeometryReader 和 Horizo​​ntal Scroll 视图有关,但不知道如何稳定它...

列表视图是:

import SwiftUI

struct AccountsListView: View 
    
    var accounts: [Accounts.AccountRecord] 
        var acctRec = [Accounts.AccountRecord]()
        acctRec = Accounts.shared.selectAllAccounts()
        return acctRec
    
    
    var body: some View 
        
        NavigationView 
            
            VStack 
                Divider().background(Color.black)
                    ForEach (accounts, id: \.self)  accountRec in
                        NavigationLink(destination: BudgetPagesView(accountCode: accountRec.account_code))
                            HStack 
                                Image(systemName: "dollarsign.circle")
                                    .padding(.leading, 15)
                                Text(accountRec.account_name)
                                Spacer()
                                Text(String(NumberFormatter.formatWithComma(value:accountRec.running_balance)))
                                    .padding(.trailing, 15)
                            
                        
                        .foregroundColor(.black)
                        Divider().background(Color.black)
                    // END FOR EACH
            // END VSTACK
            .font(.title)
            .padding(.top, 25)
            .frame(minWidth: 0,
                   maxWidth: .infinity,
                   minHeight: 0,
                   maxHeight: .infinity,
                   alignment: .topLeading
            )
            .navigationTitle("Managing Your Money Accounts")
            .navigationBarTitleDisplayMode(.inline)
            
         // END NAVIGATION VIEW
        .navigationViewStyle(StackNavigationViewStyle())
        
     // END BODY VIEW
    
 // END STRUCT VIEW

struct AccountsListView_Previews: PreviewProvider 
    static var previews: some View 
        AccountsListView().environmentObject(GlobalSettings())
            .environmentObject(ApplicationSettings())
            .environmentObject(Budget())
            .environmentObject(AppSettings())
    




子视图是:

import SwiftUI

struct BudgetPagesView: View 
    // Control the scrollview
    @GestureState private var dragOffset: CGFloat = 0
    
    // Environment variables
    @EnvironmentObject var applicationSettings: ApplicationSettings
    @EnvironmentObject var budget: Budget
    @EnvironmentObject var appSettings: AppSettings
    @EnvironmentObject var globalSettings: GlobalSettings
    @Environment(\.presentationMode) var presentationMode
    
    @State var accountCode: Int
    
    var budgets: [Budget.BudgetRecord] 
        return Budget.shared.selectBudgetForAccountAndYear(withAccountCode: accountCode, withYear: String(self.applicationSettings.currentBudgetYear))
    
    
    var body: some View 
        
            GeometryReader  outterView in
                
                    VStack 
                        HStack(spacing: 0) 
                            
                            ForEach (self.budgets, id: \.self)  record in
                                
                                GeometryReader  innerView in
                                    
                                    BudgetView(
                                        account_name: record.account_name,
                                        account_code: record.account_code,
                                        budget_month: record.budget_month,
                                        budget_year: record.budget_year,
                                        beginning_balance: record.beginning_balance,
                                        expected_income: record.expected_income,
                                        expected_income_received:record.expected_income_received,
                                        unexpected_income_received: record.unexpected_income,
                                        expected_expense: record.expected_expense,
                                        expected_expense_spent: record.expected_expense_spent,
                                        unexpected_expense: record.unexpected_expense,
                                        budgeted_surplus: record.budgeted_surplus,
                                        adjusted_surplus: record.adjusted_surplus,
                                        actual_surplus: record.actual_surplus,
                                        month_closed: record.month_closed)
                                 // END OF GEOMETRY READER INNERVIEW
                                .frame(width: outterView.size.width)
                                .contentShape(Rectangle())
                             // END OF FOREACH
                            
                         // END OF HSTACK
                        .frame(width: outterView.size.width, height: 510, alignment: .leading)
                        .offset(x: -CGFloat(self.applicationSettings.currentBudgetMonth - 1 ) * outterView.size.width)
                        .offset(x: self.dragOffset)
                        .gesture(
                            DragGesture(minimumDistance: 10, coordinateSpace: .local)
                                .updating(self.$dragOffset, body: (value, state, transaction) in
                                    state = value.translation.width
                                )
                                .onEnded( (value) in
                                    let threshold = outterView.size.width * 0.40
                                    var newIndex = Int(-value.translation.width / threshold) + self.applicationSettings.currentBudgetMonth
                                    newIndex = min(max(newIndex,1), 12)
                                    self.applicationSettings.currentBudgetMonth = newIndex
                                )
                        ) // END OF GESTURE
                        .animation(.easeInOut)

                     // END VSTACK

            // END OF GEOMETRY READER OUTTERVIEW
//            .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height, alignment: .leading)
            .navigationTitle("Managing Your Money Budget")
            .navigationBarTitleDisplayMode(.inline)
            .navigationBarBackButtonHidden(true)
            .toolbar() 
                ToolBarCancel 
                    self.presentationMode.wrappedValue.dismiss()
                
            
     // END OF BODY


struct BudgetPagesView_Previews: PreviewProvider 
    static var previews: some View 
        BudgetPagesView(accountCode: 12345678)
            .environmentObject(ApplicationSettings())
            .environmentObject(Budget())
            .environmentObject(GlobalSettings())
            .environmentObject(AppSettings())
    


【问题讨论】:

【参考方案1】:

目前您正在使用自定义水平轮播视图(或自定义 PageTabView 等),但使用带有 PageTabViewStyle() 的 TabView 会更容易,除非您想要特殊的动画。

@State var selectedTab: Int?

TabView(selection: $selectedTab) 
    ForEach (self.budgets, id: \.self)  record in
        // your code
        .tag(0)


        .tag(1)
    

.tabViewStyle(PageTabViewStyle())

【讨论】:

嗯...这当然是一个很大的改进。几乎是我的完美解决方案。现在,我只有另一个要求要满足。我想将显示为页面 # = 的页面定位到当前月份。就像九月到第 9 页一样。 @rpetruzz 很高兴听到这个消息:D 为此,您可以使用“选择”。使用selection,您可以匹配当前月份。我编辑了我的帖子以作为选择示例。 @rpetruzz 如果它不起作用,您可以发布一个包含 TabView 代码的更新代码的新问题,或者在这里提问,如果时间不长的话 :) 您好,使用我发现使用选择和.tag()。它现在可以像我希望的那样工作,并且比我的带有水平滚动视图的旧代码要好得多。感谢所有为我发帖的人..

以上是关于NavigationView 奇怪的与子视图之间的转换的主要内容,如果未能解决你的问题,请参考以下文章

如何最小化 NavigationView 中的 SearchBar 与其上方的 Text 视图之间的空间?

SwiftUI NavigationView 切换色调颜色

使用 NavigationView 和工作表删除元素时 ForEach 崩溃

SwiftUI:onAppear 的奇怪行为

如何导航到 NavigationView 内的任何视图

选择中的左连接与子查询的奇怪问题