NavigationView 奇怪的与子视图之间的转换
Posted
技术标签:
【中文标题】NavigationView 奇怪的与子视图之间的转换【英文标题】:NavigationView odd transition to and from child view 【发布时间】:2021-08-30 11:06:07 【问题描述】:我希望我可以将我的模拟器记录附加到此请求中。我有一个项目列表,我为它创建了一个 NavigationLink,它根据传入的值调用具有不同数据的子视图。子视图是一个大型水平滚动视图,其页面支持一年中的几个月。 DragGesture 控制水平滚动的位置。
当我从列表过渡到子视图时,它看起来几乎就像从右侧俯冲而入,当它过渡回父列表视图时,您可以看到两个视图的视觉效果在过渡期间短暂出现。
我相信它与 GeometryReader 和 Horizontal 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 视图之间的空间?