You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS开发:键盘弹出时在其上方放置UIView出现偏移问题求助

Fixing Offset Issue for UIView Positioned Above Keyboard

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 applyView is 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:55:00