一, 在viewDidload() 中 绑定通知,并添加键盘监听
其中绑定的 keyboardWillShow 会有动画, KeyboardDidShow 不会有 动画
func viewDidload(){ NotificationCenter.default.addObserver(self, selector: #selector(PasscodePane.keyboardWillHide(_:)),name:NSNotification.Name.UIKeyboardWillHide, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(PasscodePane.keyboardWillShow(_:)),name:NSNotification.Name.UIKeyboardWillShow, object: nil) } //释放 deinit { NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil) } func keyboardWillShow(_ sender: Notification) { //获取键盘的frame guard let keyboardFrame = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue else { return } //如果边框=0也返回 if(keyboardFrame.height == nill || keyboardFrame.height == 0){return;} UIView.animate(withDuration: 0.1, animations: { self.containerCenterConstraint?.update(offset: -keyboardFrame.height/2) self.layoutIfNeeded() }) } func keyboardWillHide(_ sender: Notification) { UIView.animate(withDuration: 0.1, animations: { self.containerCenterConstraint?.update(offset: 0) self.layoutIfNeeded() }) }
** 解决有时 或 第三方输入 触发 3次 或 多次 通知 的问题
原理是 获取 1秒 内获取到的最新的高度 ,并 1秒后才更新 UI
var keyb_ht:CGFloat = 0; var getKbHt_time_over:Bool = true; //机制: 1秒内 获取 到 的最后一次 高度 才 更新 UI , 从 第一次 触发 开始 或 1秒之后 再 触发的 第一次 开始 func keyboardWillShow(aNotification: NSNotification) { let userinfo: NSDictionary = aNotification.userInfo! as NSDictionary let nsValue = userinfo.object(forKey: UIKeyboardFrameEndUserInfoKey) let keyboardRec = (nsValue as AnyObject).cgRectValue let key_height = keyboardRec?.size.height if(key_height == 0){ return; } //更新当前最新的高度 keyb_ht = key_height!; //如果 1秒 延迟 执行UI 还没有 执行 就返回 if(getKbHt_time_over == false){ print("111") return; } print("222") getKbHt_time_over = false; DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {//1秒之后才执行 print("333") //update ui self.kb_top_view?.frame.origin.y = screenHeight - self.keyb_ht - self.kb_top_view_ht; self.getKbHt_time_over = true; } }
在执行动画的时候如果遇到 设置 动画时间无效 可用异步
DispatchQueue.main.async{
}
参考 : https://stackoverflow.com/questions/37805885/how-to-create-dispatch-queue-in-swift-3
** 输入框默认获得 焦点
textField.becomeFirstResponder()
** 火狐浏览器 关于 该方法 的 使用 源代码
class PasscodePane: UIView { let codeInputView = PasscodeInputView(passcodeSize: 4) var codeViewCenterConstraint: Constraint? var containerCenterConstraint: Constraint? fileprivate lazy var titleLabel: UILabel = { let label = UILabel() label.font = UIConstants.DefaultChromeFont label.isAccessibilityElement = true return label }() fileprivate let centerContainer = UIView() override func accessibilityElementCount() -> Int { return 1 } override func accessibilityElement(at index: Int) -> Any? { switch index { case 0: return titleLabel default: return nil } } init(title: String? = nil) { super.init(frame: CGRect.zero) backgroundColor = UIConstants.TableViewHeaderBackgroundColor titleLabel.text = title centerContainer.addSubview(titleLabel) centerContainer.addSubview(codeInputView) addSubview(centerContainer) centerContainer.snp.makeConstraints { make in make.centerX.equalTo(self) containerCenterConstraint = make.centerY.equalTo(self).constraint } titleLabel.snp.makeConstraints { make in make.centerX.equalTo(centerContainer) make.top.equalTo(centerContainer) make.bottom.equalTo(codeInputView.snp.top).offset(-PasscodeUX.TitleVerticalSpacing) } codeInputView.snp.makeConstraints { make in codeViewCenterConstraint = make.centerX.equalTo(centerContainer).constraint make.bottom.equalTo(centerContainer) make.size.equalTo(PasscodeUX.PasscodeFieldSize) } layoutIfNeeded() NotificationCenter.default.addObserver(self, selector: #selector(PasscodePane.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(PasscodePane.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) } func shakePasscode() { UIView.animate(withDuration: 0.1, animations: { self.codeViewCenterConstraint?.update(offset: -10) self.layoutIfNeeded() }, completion: { complete in UIView.animate(withDuration: 0.1, animations: { self.codeViewCenterConstraint?.update(offset: 0) self.layoutIfNeeded() }) }) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } deinit { NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil) } func keyboardWillShow(_ sender: Notification) { guard let keyboardFrame = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue else { return } UIView.animate(withDuration: 0.1, animations: { self.containerCenterConstraint?.update(offset: -keyboardFrame.height/2) self.layoutIfNeeded() }) } func keyboardWillHide(_ sender: Notification) { UIView.animate(withDuration: 0.1, animations: { self.containerCenterConstraint?.update(offset: 0) self.layoutIfNeeded() }) } }