【问题标题】:SwiftUI button glitches on keyboard dismiss键盘关闭时的 SwiftUI 按钮故障
【发布时间】:2021-12-30 22:42:56
【问题描述】:

我的视图上有一个按钮,当按下该按钮时,它会调用hideKeyboard 函数,该函数如下:

func hideKeyboard() {
    let resign = #selector(UIResponder.resignFirstResponder)
    UIApplication.shared.sendAction(resign, to: nil, from: nil, for: nil)
}

但是,当按下按钮并关闭键盘时,会在视图向下移动时按钮保持原位的位置出现故障: https://giphy.com/gifs/Z7qCDpRSGoOb9CbVRQ

可重现的例子:

import SwiftUI


struct TestView: View {
    @State private var username: String = ""
    @State private var password: String = ""
    @State private var isAnimating: Bool = false

    var lightGrey = Color(red: 239.0/255.0,
                                      green: 243.0/255.0,
                                      blue: 244.0/255.0)
    
    var body: some View {
        ZStack() {
            VStack() {
                Spacer()
                Text("Text")
                    .font(.title)
                    .fontWeight(.semibold)
                    .padding(.bottom, 15)
                    .frame(maxWidth: .infinity, alignment: .leading)
                Text("Text")
                    .font(.subheadline)
                    .padding(.bottom)
                    .frame(maxWidth: .infinity, alignment: .leading)
                TextField("username", text: $username)
                    .padding()
                    .background(self.lightGrey)
                    .cornerRadius(5.0)
                    .padding(.bottom, 20)
                SecureField("password", text: $password)
                    .padding()
                    .background(self.lightGrey)
                    .cornerRadius(5.0)
                    .padding(.bottom, 20)
                Button(action: {
                    self.hideKeyboard()
                    login()
                })
                {
                    if isAnimating {
                        ProgressView()
                            .colorScheme(.dark)
                            .font(.headline)
                            .foregroundColor(.white)
                            .padding()
                            .frame(maxWidth: .infinity)
                            .background(Color.green)
                            .cornerRadius(10.0)
                            .padding(.bottom, 20)
                    }
                    else {
                        Text("Text")
                            .font(.headline)
                            .foregroundColor(.white)
                            .padding()
                            .frame(maxWidth: .infinity)
                            .background(Color.green)
                            .cornerRadius(10.0)
                            .padding(.bottom, 20)
                    }
                }
                .disabled(username.isEmpty || password.isEmpty || isAnimating)
                Text("Text")
                    .font(.footnote)
                    .frame(maxWidth: .infinity, alignment:.leading)
                Spacer()
            }
            .padding()
            .padding(.bottom, 150)
            .background(Color.white)
        }
    }
    
    func hideKeyboard() {
        let resign = #selector(UIResponder.resignFirstResponder)
        UIApplication.shared.sendAction(resign, to: nil, from: nil, for: nil)
    }
    
    func login() {
        isAnimating = true
    }
}

struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        TestView()
    }
}

【问题讨论】:

  • 你能加入minimal reproducible example吗?没有它,调试起来将非常具有挑战性。
  • 我很抱歉。我根据您的建议编辑了问题。

标签: swift swiftui keyboard uibutton visual-glitch


【解决方案1】:

这是由于按钮内的视图替换,在下面找到一个固定的重新布局。

使用 Xcode 13.2 / iOS 15.2 测试(为演示激活了慢动画)

    Button(action: {
        self.hideKeyboard()
        login()
    })
    {
        VStack {                 // << persistent container !!
            if isAnimating {
                ProgressView()
                    .colorScheme(.dark)
            }
            else {
                Text("Text")
            }
        }
        .foregroundColor(.white)
        .font(.headline)
        .padding()
        .frame(maxWidth: .infinity)
        .background(Color.green)
        .cornerRadius(10.0)
        .padding(.bottom, 20)
    }
    .disabled(username.isEmpty || password.isEmpty || isAnimating)

【讨论】:

    【解决方案2】:

    UIApplication.shared.sendAction 和 SwiftUI 之间似乎存在冲突:隐藏键盘会启动动画,但更新 isAnimating 属性会重置它。

    改变调用顺序解决问题:

    Button(action: {
        login()
        self.hideKeyboard()
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 2020-05-17
      • 1970-01-01
      • 2020-02-20
      相关资源
      最近更新 更多