Swift -> Listen to keyboard events to get keyboard height

 

1. Bind notification in viewDidload() and add keyboard listener

The bound keyboardWillShow will have animation, KeyboardDidShow will not have animation

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)
}

//freed
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) {
	//Get the frame of the keyboard
	guard let keyboardFrame = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue else {
		return
	}
	// also return if border=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()
	})
}

 

 

 

 

 ** Fix the issue that sometimes or third-party input triggers 3 or more notifications

The principle is to get the latest height obtained within 1 second, and update the UI after 1 second 

 

 

    var keyb_ht:CGFloat = 0;
    var getKbHt_time_over:Bool = true;
    //Mechanism: The UI is updated only after the last height obtained within 1 second, starting from the first trigger or the first trigger after 1 second
    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;
        }
        //Update the current latest height
        keyb_ht = key_height!;
        //If the UI is delayed for 1 second and the UI has not been executed, return
        if(getKbHt_time_over == false){
            print("111")
            return;
        }
        print("222")
        getKbHt_time_over = false;
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {//Execute after 1 second
            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;
        }
    }

   

 

 

 

When executing animation, if you encounter invalid setting animation time, you can use asynchronous

DispatchQueue.main.async{ 

Reference:  https://stackoverflow.com/questions/37805885/how-to-create-dispatch-queue-in-swift-3

 

 

** The input box gets focus by default

textField.becomeFirstResponder()

 

 

** Firefox browser source code for using this method

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()
        })
    }
}

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326218762&siteId=291194637