在 UITextfield 中输入文本后以编程方式更改焦点



我有一个简单的视图,它有两个文本视图和一个按钮。所有控件都垂直放置。我可以使用遥控器从一个控件导航到另一个控件。但是,我正在尝试使以下方案正常工作:

  1. 用户启动应用(焦点位于第一个文本字段上)
  2. 用户进入文本字段并使用全屏键盘,然后点击"下一步"按钮
  3. 该应用程序显示第二个文本字段(全屏键盘),输入一些文本并点击"完成"按钮
  4. 应用离开全屏键盘并聚焦按钮

虽然步骤 1-3 开箱即用,但以编程方式更改焦点 (4) 不起作用。下面是一些代码:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    if(textField == self.textfieldB) {
        self.activeView = self.textfieldB;
        [self setNeedsFocusUpdate];
        [self updateFocusIfNeeded];
        return YES;
    } 
    return NO;
}

- (UIView *)preferredFocusedView中,我将返回存储在self.activeView中的任何内容(是的,它将返回按钮实例)。所有方法都按预期调用,但焦点不会更改。我在这里做错了什么?

提前感谢!

根据这个开发者论坛线程,该行为是故意的:

关闭呈现的视图控制器(如全屏键盘)时,UIKit 将自动将焦点返回到首次显示该视图控制器时的位置(如果该视图仍可聚焦)。这样,焦点就会自动返回到用户期望的位置。当前没有覆盖此行为的机制。

在类似的情况下,我在从键盘屏幕返回后延迟切换焦点。这是一个丑陋的黑客,我希望UIKit对此不要那么固执己见。

所以我遇到的建议都没有真正对我有用,包括将较新的restoresFocusAfterTransition设置为 false。

除此之外,唯一有效的方法是在 6rchid 的答案基础上构建,延迟考虑焦点引擎更新。

class EmailViewController: UIViewController {
    @IBOutlet weak var emailTextField: UITextField!
    @IBOutlet weak var submitButton: UIButton!
    private var focusedEnvironments: [UIFocusEnvironment] = [UIFocusEnvironment]()
    override var preferredFocusEnvironments: [UIFocusEnvironment] {
        return focusedEnvironments
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        restoresFocusAfterTransition = false
        focusedEnvironments = [emailTextField, submitButton]
    }
}
extension EmailViewController: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        emailTextField.isEnabled = false
        focusedEnvironments = [submitEmailButton]
        submitButton.setNeedsFocusUpdate()
        UIView.transition(with: submitEmailButton, duration: 1.0, options: .transitionCrossDissolve, animations: {
            self.submitButton.isEnabled = true
        }) { (_) in
            // re-enable this once focus updates have completed
            self.emailTextField.isEnabled = true
        }
        return true
    }
}

如果在焦点更新完成之前使UITextField保持启用状态,则焦点似乎总是希望重置为UITextField。因此,诀窍是禁用它,然后在需要时重新启用它。

如果包含的 UIViewController 将 restoresFocusAfterTransition 设置为 false 可以更改它

只需设置 restoresFocusAfterTransition = false,然后覆盖首选焦点环境

是的,您可以通过执行以下操作来实现步骤 4:

    @IBOutlet weak var loginButton: UIButton!
    var focusedView: UIView?
    override var preferredFocusedView: UIView? {
        return focusedView
    }
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        if textField == passwordTextField {
            focusedView = loginButton
        }
        return true
    }

相关内容

  • 没有找到相关文章

最新更新