SwiftUI: анимация кругов в списке

#list #animation #swiftui

#Список #Анимация #свифтуи

Вопрос:

У меня есть следующий код ниже, который я использую для создания списка с кругом в каждом элементе.

Моя цель состоит в том, чтобы иметь «анимацию заливки круга», когда представление открыто. В этом случае синий цвет должен заполнить заданный процентный уровень. Круги и список работают, однако моя анимация не запускается при загрузке списка / доступе пользователя к представлению.

Есть идеи, что я делаю не так?

 struct CircleListView: View {
    
    @State var percentage: CGFloat = 75
    
    var body: some View {
        
        List {
            ForEach(1..<10) { element in
                ZStack {
                    TrackCircle()
                    ProgressCircle(percentage: percentage)
                }
            }
        }
    }
}

struct ProgressCircle: View {
    var percentage: CGFloat
    
    var body: some View {
        ZStack {
            Circle()
                .trim(from: 0, to: (percentage * 0.01))
                .stroke(style: StrokeStyle(lineWidth: 8, lineCap: .round, lineJoin: .round))
                .fill(Color.blue)
                .rotationEffect(.degrees(270))
                .animation(.spring(response: 2.0, dampingFraction: 1.0, blendDuration: 1.0))
        }
    }
}

struct TrackCircle: View {
    var body: some View {
        ZStack {
            Circle()
                .stroke(style: StrokeStyle(lineWidth: 8))
                .fill(Color.red)
        }
    }
}

 

Большое спасибо!

Ответ №1:

Анимация начинается при обнаружении изменения свойства animatable. Предоставленный код статичен — никаких изменений во время выполнения, поэтому анимации нет.

Вот модифицированная демонстрация, которая активирует анимацию (протестирована с Xcode 12.1 / iOS 14.1)

 @State var percentage: CGFloat = 0     // << initial state

var body: some View {
    
    List {
        ForEach(1..<10) { element in
            ZStack {
                TrackCircle()
                ProgressCircle(percentage: percentage)
            }
        }
    }
    .onAppear { percentage = 75 }     // << changed state
}