Tenho a seguinte interface de usuário:
Red Rectangle
a velocidade de rotação é baseada no valor do controle deslizante. Estou conseguindo isso usando .linear(duration:).repeatForever(autoreverses: false)
(duração baseada no valor do controle deslizante) e .id
modificador para parar a animação atual sempre que o valor do controle deslizante for alterado.
struct ContentView: View {
@State private var level: Double = 0
@State private var rotation: Double = 0
var body: some View {
VStack(spacing: 16) {
Rectangle().fill(.red)
.frame(width: 100, height: 100)
.id(level)
.rotationEffect(Angle(degrees: rotation))
.animation(level > 0 ? .linear(duration: 2 / level).repeatForever(autoreverses: false) : .linear(duration: 2), value: rotation)
Spacer().frame(height: 12)
Slider(value: $level, in: 0...3, step: 1)
HStack {
Text("0")
.fontWeight(.semibold)
Spacer()
Text("1")
.fontWeight(.semibold)
Spacer()
Text("2")
.fontWeight(.semibold)
Spacer()
Text("3")
.fontWeight(.semibold)
}
}
.padding(16)
.onChange(of: level, perform: { _ in
rotation += 360
})
}
}
Meu problema atual é quando o usuário altera o valor do controle deslizante, Rectangle
ele é redefinido para o estado inicial, .id
o que cria uma falha.
Aqui está o link do vídeo de como meu código funciona atualmente: https://imgur.com/a/6bsUJzm
Minha pergunta é como obter uma transição suave entre estados quando o usuário altera o valor do controle deslizante? Quaisquer insights ou sugestões seriam apreciados!
Uma maneira de consertar é evitar usar
.repeatForever
para a animação. Em vez disso:Desde o iOS 17, uma animação que é acionada usando
withAnimation
pode ter umcompletion
retorno de chamada. Então essa seria uma maneira de acionar a animação de acompanhamento. No entanto, fazer dessa forma resulta em uma animação um tanto gaguejante.Uma técnica alternativa é usar um
Animatable
ViewModifier
para rastrear a animação e executar uma ação quando ela for concluída. Fazer dessa forma funciona mais suavemente. A resposta para SwiftUI Animation finish animation cycle fornece um modificador genérico que pode ser usado para esse propósito (foi minha resposta). Essa postagem também se preocupava com uma rotação contínua, então é um problema bem parecido.Aqui está o exemplo atualizado. Mais algumas notas:
O
.id
modificador deve ser removido.É importante que o modificador de animação apareça depois do
AnimationCompletionCallback
.Como
.repeatForever
não é mais usado, o modificador de animação pode ser simplificado (um operador ternário não é necessário).É mais simples aplicar os
.fontWeight
rótulos do controle deslizante aoHStack
, em vez de a cada rótulo individual.Você estava usando uma versão obsoleta de
.onChange
antes. Se de fato você está mirando uma versão do iOS anterior ao iOS 17, então use a versão comentada fornecida no código abaixo.