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

无实体Home键iPhone的inputAccessoryView布局适配问题

无实体Home键iPhone上inputAccessoryView布局异常问题

问题描述

  • 在无实体Home键的刘海屏iPhone上,自定义inputAccessoryView的背景视图被自身的textField和头像ImageView遮挡,常规屏幕iPhone显示正常;同时键盘弹出时的过渡动画存在异常。
  • 更新后遗留问题:将CommentAccessoryView从UIView改为UIInputView,并将子视图居中到视图本身而非安全区域后,仍存在两个问题:
    1. inputAccessoryView未识别安全区域,被底部Home指示器遮挡;
    2. UITableView内容被inputAccessoryView遮挡。

相关代码

CommentsTableViewController代码

import UIKit
import SDWebImage

class CommentsTableViewController: UITableViewController {
    
    let viewModel = CommentsViewModel()
    
    let postID: String
    let postCaption: String
    let postDate: Date
    let postAuthor: ZoogramUser
    
    var keyboardAccessoryView: CommentAccessoryView = {
        let commentAccessoryView = CommentAccessoryView()
        return commentAccessoryView
    }()
    
    init(post: UserPost) {
        self.postID = post.postID
        self.postCaption = post.caption
        self.postDate = post.postedDate
        self.postAuthor = post.author
        super.init(style: .grouped)
        self.tableView.register(PostCommentsTableViewCell.self, forCellReuseIdentifier: PostCommentsTableViewCell.identifier)
        
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "Comments"
        
        keyboardAccessoryView.delegate = self
        configureKeyboardAccessoryView()
        viewModel.getComments(for: self.postID) {
            self.tableView.reloadData()
        }
        
        tableView.backgroundColor = .systemBackground
        tableView.keyboardDismissMode = .interactive
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 100
        tableView.allowsSelection = false
        tableView.separatorStyle = .none
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        becomeFirstResponder()
    }
    
    override var inputAccessoryView: UIView? {
        keyboardAccessoryView.heightAnchor.constraint(greaterThanOrEqualToConstant: 60).isActive = true
        keyboardAccessoryView.backgroundColor = .systemOrange
        return keyboardAccessoryView
    }
    
    override var canBecomeFirstResponder: Bool {
        return true
    }
    
    
    func configureKeyboardAccessoryView() {
        guard let photoURL = AuthenticationManager.shared.getCurrentUserProfilePhotoURL() else {
            return
        }
        keyboardAccessoryView.userProfilePicture.sd_setImage(with: photoURL)
    }
}

CommentAccessoryView代码

import UIKit

protocol CommentAccessoryViewProtocol {
    func postButtonTapped(commentText: String)
}

class CommentAccessoryView: UIInputView {
    
    var delegate: CommentAccessoryViewProtocol?
    
    var userProfilePicture: UIImageView = {
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        imageView.backgroundColor = .secondarySystemBackground
        return imageView
    }()
    
    var commentTextField: AccessoryViewTextField = {
        let textField = AccessoryViewTextField()
        textField.translatesAutoresizingMaskIntoConstraints = false
        textField.backgroundColor = .systemBackground
        textField.placeholder = "Enter comment"
        textField.clipsToBounds = true
        textField.layer.borderWidth = 1
        textField.layer.borderColor = UIColor.placeholderText.cgColor
        return textField
    }()
    
    var postButton: UIButton = {
        let button = UIButton(type: .system)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.widthAnchor.constraint(equalToConstant: 30).isActive = true
        button.heightAnchor.constraint(equalToConstant: 30).isActive = true
        button.clipsToBounds = true
        button.layer.cornerRadius = 30/2
        button.setImage(UIImage(systemName: "arrow.up.circle.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 35)), for: .normal)
        button.tintColor = .systemBlue
        button.addTarget(self, action: #selector(didTapPostButton), for: .touchUpInside)
        return button
    }()
    
    override init(frame: CGRect, inputViewStyle: UIInputView.Style) {
        super.init(frame: frame, inputViewStyle: inputViewStyle)
        setupConstraints()
        backgroundColor = .systemBackground
        commentTextField.rightView = postButton
        commentTextField.rightViewMode = .always
        autoresizingMask = .flexibleHeight
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        setViewCornerRadius()
    }
    
    func setViewCornerRadius() {
        userProfilePicture.layer.cornerRadius = userProfilePicture.frame.height / 2
        commentTextField.layer.cornerRadius = commentTextField.frame.height / 2
    }
    
    func setupConstraints() {
        self.addSubviews(userProfilePicture, commentTextField)
        
        NSLayoutConstraint.activate([
            // 头像约束
            userProfilePicture.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 10),
            userProfilePicture.centerYAnchor.constraint(equalTo: self.centerYAnchor),
            userProfilePicture.widthAnchor.constraint(equalToConstant: 40),
            userProfilePicture.heightAnchor.constraint(equalToConstant: 40),
            
            // 输入框约束
            commentTextField.leadingAnchor.constraint(equalTo: userProfilePicture.trailingAnchor, constant: 10),
            commentTextField.centerYAnchor.constraint(equalTo: userProfilePicture.centerYAnchor),
            commentTextField.heightAnchor.constraint(equalToConstant: 40),
            commentTextField.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -10),
            
        ])
    }
    
    override var intrinsicContentSize: CGSize {
        return CGSize.zero
    }
    
    @objc func didTapPostButton() {
        guard let text = commentTextField.text else {
            return
        }
        commentTextField.resignFirstResponder()
        delegate?.postButtonTapped(commentText: text)
    }
}

尝试过的无效代码

override func didMoveToWindow() {
    if #available(iOS 11.0, *) {
        if let window = window {
            let bottomAnchor = bottomAnchor.constraint(lessThanOrEqualToSystemSpacingBelow: window.safeAreaLayoutGuide.bottomAnchor, multiplier: 1.0)
            bottomAnchor.isActive = true
        }
    }
}

解决方案

1. 修复inputAccessoryView被Home指示器遮挡问题

  • 调整子视图布局约束,将锚点从视图本身改为safeAreaLayoutGuide,确保内容避开底部安全区域:
    修改CommentAccessoryView的setupConstraints方法:
    func setupConstraints() {
        self.addSubviews(userProfilePicture, commentTextField)
        
        NSLayoutConstraint.activate([
            // 头像约束
            userProfilePicture.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor, constant: 10),
            userProfilePicture.centerYAnchor.constraint(equalTo: self.safeAreaLayoutGuide.centerYAnchor),
            userProfilePicture.widthAnchor.constraint(equalToConstant: 40),
            userProfilePicture.heightAnchor.constraint(equalToConstant: 40),
            userProfilePicture.bottomAnchor.constraint(lessThanOrEqualTo: self.safeAreaLayoutGuide.bottomAnchor, constant: -8),
            
            // 输入框约束
            commentTextField.leadingAnchor.constraint(equalTo: userProfilePicture.trailingAnchor, constant: 10),
            commentTextField.centerYAnchor.constraint(equalTo: userProfilePicture.centerYAnchor),
            commentTextField.heightAnchor.constraint(equalToConstant: 40),
            commentTextField.trailingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.trailingAnchor, constant: -10),
            commentTextField.bottomAnchor.constraint(lessThanOrEqualTo: self.safeAreaLayoutGuide.bottomAnchor, constant: -8),
        ])
    }
    
  • 修正intrinsicContentSize,让系统正确计算视图高度:
    override var intrinsicContentSize: CGSize {
        return CGSize(width: UIView.noIntrinsicMetric, height: UIView.noIntrinsicMetric)
    }
    

2. 修复UITableView内容被遮挡问题

  • 在CommentsTableViewController的viewDidLoad中添加内边距自动适配设置:
    tableView.contentInsetAdjustmentBehavior = .always
    
  • 移除inputAccessoryView重写中重复添加的约束,避免AutoLayout冲突:
    将高度约束和背景色设置移到viewDidLoad中:
    override func viewDidLoad() {
        // ... 其他原有代码
        keyboardAccessoryView.heightAnchor.constraint(greaterThanOrEqualToConstant: 60).isActive = true
        keyboardAccessoryView.backgroundColor = .systemOrange
    }
    
    override var inputAccessoryView: UIView? {
        return keyboardAccessoryView
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 10:25:22