iOS开发:键盘弹出时在其上方放置UIView出现偏移问题求助
Hey there! Let's figure out why your applyView is offset when the keyboard pops up. Based on your description, here are the most likely culprits and how to fix them:
Common Causes & Solutions
1. Incorrect Initial Constraint Setup
Make sure your bottom constraint is anchored to the safe area bottom (not the view's bottom) and stored properly. If you're setting it to the view's bottom, on devices with a home indicator, this will cause an offset when the keyboard hides that indicator.
2. Not Syncing Animation with Keyboard
The keyboard animates in/out with specific duration and curve. If you update your constraint without matching that animation, the view will move out of sync, looking like it's offset.
3. Not Accounting for Keyboard's Actual Visible Height
Sometimes the keyboard's frame includes additional insets (like the safe area bottom inset), so you need to subtract that from the keyboard height to get the correct distance from the safe area.
Corrected Implementation
Here's a revised version of your code that addresses these issues:
class CompanyDetailViewController: UIViewController { var applyView: ApplyView! private var applyViewBottomConstraint: NSLayoutConstraint? override func viewDidLoad() { super.viewDidLoad() // 1. Create and configure the applyView applyView = ApplyView() applyView.isHidden = true applyView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(applyView) // 2. Set up constraints (anchor to safe area) NSLayoutConstraint.activate([ applyView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), applyView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), applyView.heightAnchor.constraint(equalToConstant: 60) // Adjust height as needed ]) // Store the bottom constraint separately (initially set to safe area bottom) applyViewBottomConstraint = applyView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) applyViewBottomConstraint?.isActive = true // 3. Register for keyboard notifications NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil) } @objc private func keyboardWillShow(_ notification: Notification) { guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return } let keyboardHeight = keyboardFrame.height // Get the safe area bottom inset to adjust (for home indicator) let safeAreaBottomInset = view.safeAreaInsets.bottom let adjustedKeyboardHeight = keyboardHeight - safeAreaBottomInset // Update the bottom constraint constant applyViewBottomConstraint?.constant = -adjustedKeyboardHeight // Animate the constraint change to match keyboard animation if let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval, let curve = notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt { UIView.animate(withDuration: duration, delay: 0, options: UIView.AnimationOptions(rawValue: curve)) { self.view.layoutIfNeeded() } completion: { _ in self.applyView.isHidden = false } } else { view.layoutIfNeeded() applyView.isHidden = false } } @objc private func keyboardWillHide(_ notification: Notification) { // Reset the bottom constraint applyViewBottomConstraint?.constant = 0 // Animate the constraint change to match keyboard animation if let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval, let curve = notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt { UIView.animate(withDuration: duration, delay: 0, options: UIView.AnimationOptions(rawValue: curve)) { self.view.layoutIfNeeded() } completion: { _ in self.applyView.isHidden = true } } else { view.layoutIfNeeded() applyView.isHidden = true } } deinit { // Don't forget to remove observers to avoid memory leaks NotificationCenter.default.removeObserver(self) } }
Key Fixes Explained
- Safe Area Anchoring: The
applyViewis anchored to the safe area, so it won't be affected by the home indicator. - Adjusted Keyboard Height: We subtract the safe area bottom inset from the keyboard height to get the correct distance the view needs to move up.
- Synced Animation: The constraint update is wrapped in an animation block that uses the keyboard's own duration and curve, so the view moves perfectly in sync with the keyboard.
- Proper Constraint Activation: The bottom constraint is stored and activated correctly, ensuring updates are applied properly.
Give this a try—this should resolve the offset issue you're seeing!
内容的提问来源于stack exchange,提问作者Hideaki Touhara

