1

I have a problem regarding behavior of an animated loading view. The loading view shows up while the network call. I have an isLoading @Published var inside my viewModel and the ActivityIndicator is shown inside a ZStack in my view. The Activityindicator is a custom view where I animate a trimmed circle - rotate it. Whenever the activity indicator is shown inside my mainView it has a weird transition when appearing- it is transitioned from the top left corner to the center of the view. Does anyone know why is this happening? I attach the structs with the code and 3 pictures with the behavior. ActivityIndicator:

struct OrangeActivityIndicator: View {
    var style = StrokeStyle(lineWidth: 6, lineCap: .round)
    @State var animate = false
    let orangeColor = Color.orOrangeColor
    let orangeColorOpaque = Color.orOrangeColor.opacity(0.5)
    
    init(lineWidth: CGFloat = 6) {
        style.lineWidth = lineWidth
    }
    
    var body: some View {
        ZStack {
            CircleView(animate: $animate, firstGradientColor: orangeColor, secondGradientColor: orangeColorOpaque, style: style)
        }.onAppear() {
            self.animate.toggle()
        }
    }
}

struct CircleView: View {
    @Binding var animate: Bool
    var firstGradientColor: Color
    var secondGradientColor: Color
    var style: StrokeStyle
    
    var body: some View {
        Circle()
            .trim(from: 0, to: 0.7)
            .stroke(
                AngularGradient(gradient: .init(colors: [firstGradientColor, secondGradientColor]), center: .center), style: style
            )
            .rotationEffect(Angle(degrees: animate ? 360 : 0))
            .transition(.opacity)
            .animation(Animation.linear(duration: 0.7) .repeatForever(autoreverses: false), value: animate)
    }
}

The view is use it in :

struct UserProfileView: View {
    @ObservedObject var viewModel: UserProfileViewModel
    @Binding var lightMode: ColorScheme

    var body: some View {
        NavigationView {
            ZStack {
                VStack(alignment: .center, spacing: 12) {
                    HStack {
                        Text(userProfileEmail)
                            .font(.headline)
                            .foregroundColor(Color(UIColor.label))
                        Spacer()
                    }.padding(.bottom, 16)
                    SettingsView(userProfile: $viewModel.userProfile, isDarkMode: $viewModel.isDarkMode, lightMode: $lightMode, location: viewModel.locationManager.address, viewModel: viewModel)
                    ButtonsView( userProfile: $viewModel.userProfile)
                    Spacer()

                }.padding([.leading, .trailing], 12)

                if viewModel.isLoading {
                    OrangeActivityIndicator()
                        .frame(width: 40, height: 40)
//                        .animation(nil)
                }
            }
        }
    }
}

I also tried with animation nil but it doesn't seem to work. Here are the pictures: enter image description here enter image description here enter image description here

Adrian Macarenco
  • 165
  • 2
  • 11
  • try to put a clear Rectangle() with maxWidth and maxHeight to .infinity before VStack and ZStack(alignment: .topLeading) – Simone Pistecchia Mar 01 '21 at 12:50
  • ZStack(alignment: .topLeading) { Rectangle() .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.clear) VStack(alignment: .center, spacing: 12) {.... } if viewModel.isLoading { OrangeActivityIndicator() .frame(width: 40, height: 40) .animation(nil) } } I tried this and it doesn't work – Adrian Macarenco Mar 01 '21 at 13:45
  • it's working in this way? – Simone Pistecchia Mar 01 '21 at 13:53
  • no. I added as you said a Rectangle with a frame of maxWidth and maxHeight both .infinity and background Color.clear before the VStack in the ZStack body. ANd ZStack Alignment topLeading. It doesn't work :( – Adrian Macarenco Mar 01 '21 at 13:55

1 Answers1

3

Here is a possible solution - put it over NavigationView. Tested with Xcode 12.4 / iOS 14.4

    NavigationView {

       // .. your content here

    }
    .overlay(                    // << here !!
        VStack {
            if isLoading {
                OrangeActivityIndicator()
                    .frame(width: 40, height: 40)
            }
        }
    )
Asperi
  • 228,894
  • 20
  • 464
  • 690