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

iOS开发:用户输入时如何将UIButton附着在键盘上,求示例代码

实现方案(Swift 版)

核心思路

监听系统键盘的弹出/隐藏通知,获取键盘的动画参数与高度,同步调整底部按钮的底部约束,让按钮跟随键盘动画同步上浮/下沉。

完整示例代码

import UIKit

class ViewController: UIViewController {
    // 底部操作按钮
    private let bottomButton: UIButton = {
        let btn = UIButton(type: .system)
        btn.setTitle("提交操作", for: .normal)
        btn.backgroundColor = .systemBlue
        btn.setTitleColor(.white, for: .normal)
        btn.layer.cornerRadius = 8
        btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
        return btn
    }()
    
    // 输入文本框
    private let textView: UITextView = {
        let tv = UITextView()
        tv.layer.borderWidth = 1
        tv.layer.borderColor = UIColor.systemGray5.cgColor
        tv.layer.cornerRadius = 8
        tv.font = .systemFont(ofSize: 15)
        return tv
    }()
    
    // 按钮底部约束,后续动态修改该值实现位移
    private var buttonBottomConstraint: NSLayoutConstraint!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        setupKeyboardObserver()
    }
    
    // 布局基础控件
    private func setupUI() {
        view.backgroundColor = .white
        
        [textView, bottomButton].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview($0)
        }
        
        buttonBottomConstraint = bottomButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16)
        
        NSLayoutConstraint.activate([
            textView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
            textView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            textView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
            textView.heightAnchor.constraint(equalToConstant: 200),
            
            bottomButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            bottomButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
            bottomButton.heightAnchor.constraint(equalToConstant: 48),
            buttonBottomConstraint
        ])
        
        // 点击空白处收起键盘
        let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
        view.addGestureRecognizer(tap)
    }
    
    // 注册键盘状态监听
    private func setupKeyboardObserver() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    // 键盘弹出逻辑处理
    @objc private func keyboardWillShow(notification: NSNotification) {
        guard let userInfo = notification.userInfo,
              let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect,
              let animationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else { return }
        
        let keyboardHeight = keyboardFrame.height
        let safeAreaBottom = view.safeAreaInsets.bottom
        // 按钮上移后和键盘顶部保留16px间距
        let offset = -(keyboardHeight - safeAreaBottom + 16)
        
        buttonBottomConstraint.constant = offset
        UIView.animate(withDuration: animationDuration) {
            self.view.layoutIfNeeded()
        }
    }
    
    // 键盘隐藏逻辑处理
    @objc private func keyboardWillHide(notification: NSNotification) {
        guard let userInfo = notification.userInfo,
              let animationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else { return }
        
        // 按钮恢复到初始位置
        buttonBottomConstraint.constant = -16
        UIView.animate(withDuration: animationDuration) {
            self.view.layoutIfNeeded()
        }
    }
    
    @objc private func dismissKeyboard() {
        view.endEditing(true)
    }
    
    // 移除通知避免内存泄漏
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

实现效果参考

设计参考示意图

注意事项

  • 必须通过修改自动布局约束的方式实现位移,不要直接修改按钮frame,否则会出现动画和键盘不同步的问题
  • 代码自动适配各类键盘高度(包括emoji键盘、外接键盘、带输入建议栏的键盘等场景)
  • 如需兼容Objective-C版本,核心逻辑完全一致,仅需要替换为对应OC语法即可

内容的提问来源于stack exchange,提问作者JOhn Mic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 23:12:05