SwiftUI:输入无效时文本字段摇动动画
SwiftUI: Textfield shake animation when input is not valid
我想在用户按下“保存”按钮且输入无效时创建摇动动画。我的第一种方法是这样的(为了简化我删除了修饰符而不是这种情况下的相关属性):
查看:
struct CreateDeckView: View {
@StateObject var viewModel = CreateDeckViewModel()
HStack {
TextField("Enter title", text: $viewModel.title)
.offset(x: viewModel.isValid ? 0 : 10) //
.animation(Animation.default.repeatCount(5).speed(4)) // shake animation
Button(action: {
viewModel.buttonPressed = true
viewModel.saveDeck(){
self.presentationMode.wrappedValue.dismiss()
}
}, label: {
Text("Save")
})
}
}
视图模型:
class CreateDeckViewModel: ObservableObject{
@Published var title: String = ""
@Published var buttonPressed = false
var validTitle: Bool {
buttonPressed && !(title.trimmingCharacters(in: .whitespacesAndNewlines) == "")
}
public func saveDeck(completion: @escaping () -> ()){ ... }
}
但是这个解决方案并没有真正起作用。当我第一次按下按钮时,什么也没有发生。之后,当我更改文本字段时,它开始摇晃。
使用GeometryEffect
,
struct ContentView: View {
@StateObject var viewModel = CreateDeckViewModel()
var body: some View {
HStack {
TextField("Enter title", text: $viewModel.title)
.modifier(ShakeEffect(shakes: viewModel.shouldShake ? 2 : 0)) //<- here
.animation(Animation.default.repeatCount(6).speed(3))
Button(action: {
viewModel.saveDeck(){
...
}
}, label: {
Text("Save")
})
}
}
}
//here
struct ShakeEffect: GeometryEffect {
func effectValue(size: CGSize) -> ProjectionTransform {
return ProjectionTransform(CGAffineTransform(translationX: -30 * sin(position * 2 * .pi), y: 0))
}
init(shakes: Int) {
position = CGFloat(shakes)
}
var position: CGFloat
var animatableData: CGFloat {
get { position }
set { position = newValue }
}
}
class CreateDeckViewModel: ObservableObject{
@Published var title: String = ""
@Published var shouldShake = false
var validTitle: Bool {
!(title.trimmingCharacters(in: .whitespacesAndNewlines) == "")
}
public func saveDeck(completion: @escaping () -> ()){
if !validTitle {
shouldShake.toggle() //<- here (you can use PassThrough subject insteadof toggling.)
}
}
}
我想在用户按下“保存”按钮且输入无效时创建摇动动画。我的第一种方法是这样的(为了简化我删除了修饰符而不是这种情况下的相关属性):
查看:
struct CreateDeckView: View {
@StateObject var viewModel = CreateDeckViewModel()
HStack {
TextField("Enter title", text: $viewModel.title)
.offset(x: viewModel.isValid ? 0 : 10) //
.animation(Animation.default.repeatCount(5).speed(4)) // shake animation
Button(action: {
viewModel.buttonPressed = true
viewModel.saveDeck(){
self.presentationMode.wrappedValue.dismiss()
}
}, label: {
Text("Save")
})
}
}
视图模型:
class CreateDeckViewModel: ObservableObject{
@Published var title: String = ""
@Published var buttonPressed = false
var validTitle: Bool {
buttonPressed && !(title.trimmingCharacters(in: .whitespacesAndNewlines) == "")
}
public func saveDeck(completion: @escaping () -> ()){ ... }
}
但是这个解决方案并没有真正起作用。当我第一次按下按钮时,什么也没有发生。之后,当我更改文本字段时,它开始摇晃。
使用GeometryEffect
,
struct ContentView: View {
@StateObject var viewModel = CreateDeckViewModel()
var body: some View {
HStack {
TextField("Enter title", text: $viewModel.title)
.modifier(ShakeEffect(shakes: viewModel.shouldShake ? 2 : 0)) //<- here
.animation(Animation.default.repeatCount(6).speed(3))
Button(action: {
viewModel.saveDeck(){
...
}
}, label: {
Text("Save")
})
}
}
}
//here
struct ShakeEffect: GeometryEffect {
func effectValue(size: CGSize) -> ProjectionTransform {
return ProjectionTransform(CGAffineTransform(translationX: -30 * sin(position * 2 * .pi), y: 0))
}
init(shakes: Int) {
position = CGFloat(shakes)
}
var position: CGFloat
var animatableData: CGFloat {
get { position }
set { position = newValue }
}
}
class CreateDeckViewModel: ObservableObject{
@Published var title: String = ""
@Published var shouldShake = false
var validTitle: Bool {
!(title.trimmingCharacters(in: .whitespacesAndNewlines) == "")
}
public func saveDeck(completion: @escaping () -> ()){
if !validTitle {
shouldShake.toggle() //<- here (you can use PassThrough subject insteadof toggling.)
}
}
}