首页 > 解决方案 > 键盘折叠时 inputAccessoryView 不遵守 safeAreaLayoutGuide

问题描述

我正在尝试让 inputAccessoryView 正常工作。也就是说,在这种情况下,我希望能够以两种可能的状态显示 UIToolbar:

  1. 键盘上方 - 标准和预期行为
  2. 当键盘被关闭时在屏幕底部(例如模拟器中的 command + K) - 在这种情况下,让bottomAnchor 尊重底部的safeAreaLayoutGuide。

我已经广泛研究了这个主题,但我能找到的每一个建议都有一堆似乎与 Apple 工程建议的解决方案不一致的解决方法。基于 openradar 票证,Apple 工程师提出了这个解决方案,方法如下:

尊重输入附件视图的 safeAreaInsets 是您的责任。我们以这种方式设计它,以便开发人员可以提供背景视图(即,参见 Safari 的 Find on Page 输入辅助视图)并根据 safeAreaInsets 布置内容视图。这很容易实现。有一个视图层次结构,其中有一个容器视图和一个内容视图。容器视图可以具有背景颜色或包含其整个边界的背景视图,并且它基于 safeAreaInsets 布置其内容视图。如果您使用自动布局,这就像将内容视图的底部锚点设置为等于它的超级视图的 safeAreaLayoutGuide 一样简单。

以上链接为:http ://www.openradar.me/34411433

因此,我构建了一个简单的 xCode 项目(iOS App 模板),其中包含以下代码:

class ViewController: UIViewController {
    
    var field = UITextField()
    var containerView = UIView()
    var contentView = UIView()
    var toolbar = UIToolbar()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        // TEXTFIELD
        field = UITextField(frame: CGRect(x: 20, y: 100, width: view.frame.size.width, height: 50))
        field.placeholder = "Enter name..."
        field.backgroundColor = .secondarySystemBackground
        field.inputAccessoryView = containerView
        view.addSubview(field)
        
        // CONTAINER VIEW
        containerView.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: 50)
        containerView.backgroundColor = .systemYellow
        containerView.translatesAutoresizingMaskIntoConstraints = false
                
        // CONTENT VIEW
        contentView.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: 50)
        contentView.backgroundColor = .systemPink
        contentView.translatesAutoresizingMaskIntoConstraints = false
        containerView.addSubview(contentView)
        
        // TOOLBAR
        toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 50))
        let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
        let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(didTapDone))
        toolbar.setItems([flexibleSpace, doneButton], animated: true)
        toolbar.backgroundColor = .systemGreen
        toolbar.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(toolbar)
        
        NSLayoutConstraint.activate([
            contentView.topAnchor.constraint(equalTo: containerView.topAnchor),
            contentView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
            contentView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
            contentView.bottomAnchor.constraint(equalTo: contentView.superview!.safeAreaLayoutGuide.bottomAnchor),

            toolbar.topAnchor.constraint(equalTo: contentView.topAnchor),
            toolbar.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            toolbar.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            toolbar.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
        ])
    }
    
    
    @objc private func didTapDone() {
        print("done tapped")
    }
}

结果在键盘可见时有效,但在键盘关闭后无效:

键盘可见

在此处输入图像描述

我玩弄了各种视图的高度,结果混合在一起,并使容器视图框架的高度更大(例如 100),当键盘折叠时确实显示工具栏,它也使工具栏太高,不适合键盘可见的。

显然,我正在解决一些自动布局约束问题,但我无法解决,并且希望任何提供符合 Apple 建议的可行解决方案的反馈。

提前致谢。

标签: iosswiftautolayoutinputaccessoryview

解决方案


就我而言,我使用以下方法:

import UIKit

extension UIView {
    
    
    
   
    
    func setDimensions(height: CGFloat, width: CGFloat) {
        translatesAutoresizingMaskIntoConstraints = false
        heightAnchor.constraint(equalToConstant: height).isActive = true
        widthAnchor.constraint(equalToConstant: width).isActive = true
    }
    
    func setHeight(_ height: CGFloat) {
        translatesAutoresizingMaskIntoConstraints = false
        heightAnchor.constraint(equalToConstant: height).isActive = true
    }
}



class CustomTextField: UITextField {
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    convenience init(placeholder: String) {
        self.init(frame: .zero)
        configureUI(placeholder: placeholder)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func configureUI(placeholder: String) {
        
        let spacer = UIView()
        spacer.setDimensions(height: 50, width: 12)
        leftView = spacer
        leftViewMode = .always
        
        borderStyle = .none
        textColor = .white
        keyboardAppearance = .dark
        backgroundColor = UIColor(white: 1, alpha: 0.1)
        setHeight(50)
        attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [.foregroundColor: UIColor(white: 1, alpha: 0.75)])
        
        
    }
}

 

推荐阅读