【发布时间】:2021-11-21 20:48:44
【问题描述】:
从InsightsHomeView 列表中的任何项目转换到InsightsCard 时,我遇到了奇怪的动画行为。知道什么可能导致此问题或如何解决?
//从此视图导航:
struct InsightsHomeView: View {
var body: some View {
NavigationView {
VStack {
if historicalDataManager.arrayOfCareerMaxSpeedValuesAsCustomHistoricalSample.count > 0 {
List {
Section(header: Text("Speed & Distance")) {
NavigationLink(destination: InsightsCard(insightChartDataObject: InsightChartDataObject(insightChartType: .maxSpeed, customHistoricalSamples: historicalDataManager.arrayOfCareerMaxSpeedValuesAsCustomHistoricalSample, insightChartDataName: "Max Speed", insightChartColor: colorScheme == .dark ? Color(logoAquaShade5Color) : Color(logoBlueColor)))) {
//Label("Max Speed", systemImage: "speedometer")
//Label("Max Speed", image: "maxSpeedV3iPhoneGrey")
InsightsLabel(metricName: "Max Speed", imageName: "MaxSpeediPhoneV3")
}
NavigationLink(destination: InsightsCard(insightChartDataObject: InsightChartDataObject(insightChartType: .averageBurst, customHistoricalSamples: historicalDataManager.arrayOfCareerAverageSpeedBurstValuesAsCustomHistoricalSample, insightChartDataName: "Average Burst", insightChartColor: colorScheme == .dark ? Color(logoAquaShade5Color) : Color(logoBlueColor)))) {
//Label("Average Burst", systemImage: "bolt")
InsightsLabel(metricName: "Average Burst", imageName: "AverageBurst_skate")
}
NavigationLink(destination: InsightsCard(insightChartDataObject: InsightChartDataObject(insightChartType: .distanceSkated, customHistoricalSamples: historicalDataManager.arrayOfCareerDistanceSkatedValuesAsCustomHistoricalSample, insightChartDataName: "Distance Skated", insightChartColor: colorScheme == .dark ? Color(logoAquaShade5Color) : Color(logoBlueColor), ignoreZero: true))) {
// Label("Distance Skated", systemImage: "arrow.right")
InsightsLabel(metricName: "Distance Skated", imageName: "DistanceSkatediPhoneV3")
}
}
} //end of list
} else {
HStack {
Spacer()
VStack {
Text("Loading Trends Data...")
if #available(iOS 15.0, *) {
ProgressView()
.tint(Color(logoBlueColor))
.scaleEffect(1.5)
} else {
ProgressView()
.scaleEffect(1.5)
}
}
Spacer()
}
.frame(height: 225)
}
}
.navigationTitle("Browse")
.listStyle(InsetGroupedListStyle())
.listRowBackground(colorScheme == .dark ? Color(.secondarySystemBackground) : Color(.systemBackground))
}
.background(Color(colorScheme == .dark ? .black : .secondarySystemBackground))
}
}
struct InsightsLabel: View {
var metricName: String
var imageName: String
@Environment(\.colorScheme) var colorScheme
var body: some View {
Label {
Text(metricName)
.font(.custom(futuraMedium, size: headlineTextSize))
} icon: {
Image(imageName)
.resizable()
.scaledToFit()
.foregroundColor(colorScheme == .dark ? .white : Color(logoBlueColor))
//.frame(width: 15, height: 15)
}
}
}
//到这个视图:
struct InsightsCard: View {
var insightChartDataObject: InsightChartDataObject
@State var filterdInsightChartDataObject: InsightChartDataObject?
static let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .none
return formatter
}()
var body: some View {
ScrollView {
VStack(alignment: .leading) {
ZStack {
(colorScheme == .dark ? Color(.secondarySystemBackground) : Color(.systemBackground)) //card background color
.cornerRadius(10)
VStack {
HStack {
VStack(alignment: .leading) {
Text(insightChartDataObject.insightChartDataName)
.font(.custom(futuraLTPro, size: titleTextSize))
.padding(.bottom)
.unredacted()
.opacity(subscriptionIsActive ? 1 : 0.15)
HStack {
VStack {
LargeBasicMetricView(metric: "Max", metricValueAsString: formatDataForLargeBasicMetricView(metricViewType: .max), hasUnitValue: true, unitString: getSuffixForLargeBasicMetricView())
}
.padding(.trailing)
LargeBasicMetricView(metric: "Last", metricValueAsString: formatDataForLargeBasicMetricView(metricViewType: .last), hasUnitValue: true, unitString: getSuffixForLargeBasicMetricView())
}
}
Spacer()
}
SwiftUIModularTrendChart(insightChartDataObject: filterdInsightChartDataObject ?? insightChartDataObject)
.opacity(subscriptionIsActive ? 1 : 0.25)
switch insightChartDataObject.insightChartType {
case .heartRateRecovery:
BarScaleViewInt(valueToBeScaled: 0, scaleMax: 60, numberOfBlocks: 5, colors: [UIColor(Color.red).withAlphaComponent(0.5), UIColor(Color.red).withAlphaComponent(0.6), UIColor(Color.red).withAlphaComponent(0.75), UIColor(Color.red).withAlphaComponent(0.9), UIColor(Color.red)], blockValues: [0, 12, 24, 36, 48], blockNames: ["poor", "average", "good", "excellent", "superior"], lastBlockValue: 60)
.padding(.bottom)
case .hockeyFitnessLevel:
BarScaleViewInt(valueToBeScaled: 0, scaleMax: 300, numberOfBlocks: 4, colors: [orangeShade2Color, orangeShade3Color, orangeShade4Color, orangeShade5Color], blockValues: [0, 75, 150, 225], blockNames: ["poor", "average", "good", "McDavid"], lastBlockValue: 300)
.padding(.bottom)
case .skateEfficiency:
BarScaleViewDouble(valueToBeScaled: 0, scaleMax: 2.0, numberOfBlocks: 4, colors: [orangeShade2Color, orangeShade3Color, orangeShade4Color, orangeShade5Color], blockValues: [0, 0.5, 1.0, 1.5], blockNames: ["poor", "average", "good", "McDavid"], lastBlockValue: 2.0, decimalPlaces: 1)
.padding(.bottom)
case .vo2Max:
BarScaleViewInt(valueToBeScaled: 0, scaleMax: 72, numberOfBlocks: 4, colors: [logoRedShade1Color, logoRedShade2Color, logoRedShade3Color, logoRedShade4Color], blockValues: [0, 18, 36, 54], blockNames: ["poor", "average", "good", "excellent"], lastBlockValue: 72)
.padding(.bottom)
default: EmptyView()
}
switch insightChartDataObject.insightChartType {
case .heartRateRecovery:
Text("Heart rate recovery, or HRR, is a measurement of how quickly your pulse returns to its resting rate after intense exercise. This is one of the best indicators of your cardio fitness. After performing strenuous exercise for a given period of time, HRR is calculated by taking your peak heart rate during the exercise, and then subtracting your recovered heart rate 1 or 2 minutes later. So for example if your heart rate during exercise is 180 BPM, and 2 minutes after you stop your heart rate is 110 BPM, your HRR would be 70. The higher the HRR the better.")
.fixedSize(horizontal: false, vertical: true) //this prevents this text from being truncated
.padding()
case .hockeyFitnessLevel:
Text("Hockey Fitness Level® is a ratio using your weight, max speed, and heart rate (at the time of your max speed) that gives an indication of your fitness level. The faster you can skate at a lower heart rate, the higher your Hockey Fitness Level and vice versa.")
.fixedSize(horizontal: false, vertical: true) //this prevents this text from being truncated
.padding()
case .skateEfficiency:
Text("Skating Efficiency® is a measure of how aerobically efficiently you skate based on your speed and heart rate. HockeyTracker calculates SE based on your top skating speeds and your heart rates during the times the speed samples were measured.")
.fixedSize(horizontal: false, vertical: true) //this prevents this text from being truncated
.padding()
case .vo2Max:
Text("VO2 Max is the measurement of the maximum amount of oxygen that an individual can utilize during intense, or maximal exercise. It is measured as milliliters of oxygen used in one minute per kilogram of body weight. HockeyTracker estimates your VO2 max based on your heart rate during hockey and your resting heart rate which is queried from the Health App.")
.fixedSize(horizontal: false, vertical: true) //this prevents this text from being truncated
.padding()
case .effortLevel:
Text("Effort Level uses heart rate data to measure how much cardiovascular work a player puts forth during a session. To determine an Effort Level score, we look at the cumulative time spent in each of the 5 heart rate zones. Each zone is progressively weighted higher. These zones are customized to each player based on the last 5 workouts. This customization allows two players to compare effort even though they may have different heart rate maxes. Your personalized zones are shown underneath the Effort Level pie chart. So for example if your personalized max heart rate zone is 183 bpm - 210 bpm, if you log a lot of time in this zone, your Effort Level score is going to rank higher. Alternatively, if you have a relatively easy skate and the bulk of your heart rate samples are in the lowest zone, your Effort Level score will rank lower.")
.fixedSize(horizontal: false, vertical: true) //this prevents this text from being truncated
.padding()
default: EmptyView()
}
}
.padding([.vertical, .leading])
if !subscriptionIsActive {
Button(action: {
pushToSubscribeVC()
}) {
CardLockButtonView(goProText: "Unlock Historical Charts and Personal Records with HockeyTracker Pro", buttonHeight: 120, showIcon: true)
.padding(.horizontal)
}
}
}
.padding(.horizontal)
} //end of Master VStack
.if(!subscriptionIsActive) { $0.redacted(reason: .placeholder) }
.navigationBarItems(trailing:
Button(action: {
}) {
Menu("Filter") {
ForEach(allSessionTypes, id: \.self) { sessionType in
Button(sessionType, action: {
filterdInsightChartDataObject = InsightChartDataObject(insightChartType: insightChartDataObject.insightChartType, customHistoricalSamples: insightChartDataObject.customHistoricalSamples.filter { $0.sessionType?.rawValue ?? "Game" == sessionType }, insightChartDataName: insightChartDataObject.insightChartDataName, insightChartColor: insightChartDataObject.insightChartColor)
})
}
}
}
)
.background(Color(colorScheme == .dark ? .black : .secondarySystemBackground)) //background color
} //endOfScrollView
}
}
【问题讨论】:
-
这是 NavigationView 的 bug!你的代码太小了,难以阅读!你在某些地方使用动画吗?或者您是在子视图或父视图中开始关于颜色或位置的动画吗?我需要知道与动画相关的位置和内容以及如何被解雇。
-
@swiftPunk 谢谢,对不起,我试图删除它的一部分,以便您可以看到我正在做的一切,以防万一导致这种行为意外。我没有在任何地方使用任何动画,这就是为什么它如此奇怪? ????♂️
-
如果您从代码中删除更多好的部分,您可以验证这不会导致问题,这将非常有帮助。此外,当您不小心删除了 bad 位时,您可能会知道是哪个位导致了这种行为;)
-
那么这个问题是因为 NavigationLink 触发了 NavigationView 错误!首先尝试这个测试,从链接中删除图像并运行项目并告诉我会发生什么。
-
@swiftPunk 我尝试在 NavigationLink 中嵌入一个 Text() (无图像),结果相同。我清理了一些代码,还添加了我未能包含的
InsightsLabel的代码。 ???仍然不知道可能是什么原因?
标签: ios swift swiftui swiftui-navigationview swiftui-animation