1

I'm experiencing a strange animation behavior when transitioning from any item in the List of InsightsHomeView to InsightsCard Any idea what could cause this or how to fix? enter image description here

//Navigating from this view:

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)
        }
    }
}

//To this view:

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
         
       
    }
    
    
    
    
}
GarySabo
  • 5,806
  • 5
  • 49
  • 124
  • This is a bug of NavigationView! your codes are so packet and difficult to read! are u using animation in some where? or are you starting an animation about color or position in child view or parent view? I need to know where and what connected to animation and how get fired. – ios coder Sep 30 '21 at 01:38
  • @swiftPunk thanks, sorry I tried to remove a good bit of it just so you can see everything I'm doing, in case something is causing this behavior unintended. I am not using any animation anywhere which is why it is so strange? ‍♂️ – GarySabo Sep 30 '21 at 02:26
  • It would be tremendously helpful if you would remove a couple more good bits from the code where you can verify that this is not causing the trouble. Also, you might then tell which bit is causing this behavior when you accidentally removed a _bad_ bit ;) – CouchDeveloper Sep 30 '21 at 06:52
  • So then this issue is because of NavigationLink which triggers NavigationView bug! Try this test first, remove images from Links and run the project and tell me what happens. – ios coder Sep 30 '21 at 07:37
  • @swiftPunk I tried embedding just a Text() in NavigationLink (no image) and same result. I cleaned up a little bit of the code and also added the code for `InsightsLabel` which I had failed to include. Still puzzled what the cause might be? – GarySabo Sep 30 '21 at 15:08
  • This issue happens with kind of update in UI before view get completely visible, for now I don’t have any other ideas, maybe some one can debugging the project and solving issue for you. – ios coder Sep 30 '21 at 15:47

1 Answers1

0

you have to wrap your second view in a NavigationView that should resolve the issue. There's also a secondary issue if you haven't filled the screen with content and are using a Spacer to move items to the top of a VStack.

It's a bit of a hack but if you place an empty scrollview at the bottom that can resolve the secondary issue

  • A good answer will always include an explanation why this would solve the issue, so that the OP and any future readers can learn from it. – Tyler2P Dec 08 '21 at 22:56
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 09 '21 at 01:50