10

基本上我试图在 inputAccessoryView 属性中创建一个调整大小的 UITextView 。

我有一个 viewController,其方法 canBecomeFirstResponder 返回 true,我通过自定义类(从 XIB 获取它)实例化了一个视图。在这个视图中是一个 UITextView 位于。

我尝试从该类内部调整完整的 inputAccessoryView 的大小。我尝试了几种方法:直接设置框架,尝试使用高度约束。它似乎只调整了一半:

这基本上是我想要的(有或没有自动布局,但在 iOS 7/8+ 中工作):

class MessageInputAccessory: UIView, UITextViewDelegate
{
    @IBOutlet weak var textView: UITextView!

    func textViewDidChange(textView: UITextView)
    {
        var contentSize = textView.sizeThatFits(CGSizeMake(textView.frame.size.width, CGFloat.max))

        self.frame.size.height = contentSize.height + 20

        self.textView.reloadInputViews()
    }
}

我找到了这篇文章:在 iOS 8 中更改 inputAccessoryView 的框架。说明正在创建一个自动创建的约束。问题是,它不会为我创造约束。绝不会禁用或启用自动布局(也通过 setTranslatesAutoresizingMaskIntoConstraints())。

4

3 回答 3

10

它适用于 iOS7/iOS8:

class MessageInputAccessory: UIView, UITextViewDelegate {
    private var textView: UITextView!
    private var heightConstraint: NSLayoutConstraint?

    override init(frame: CGRect) {
        super.init(frame: frame)

        commonInit()
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        commonInit()
    }

    func commonInit() {
        self.userInteractionEnabled = true

        textView = UITextView()
        textView.delegate = self
        textView.bounces = false
        textView.scrollEnabled = false
        textView.layer.cornerRadius = 5
        textView.layer.borderWidth = 1
        textView.layer.borderColor = UIColor.blueColor().CGColor

        self.addSubview(textView)
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        textView.frame = self.bounds
    }

    override func addConstraint(constraint: NSLayoutConstraint) {
        self.heightConstraint = constraint

        super.addConstraint(constraint)
    }

    func textViewDidChange(textView: UITextView) {
        var contentSize = textView.sizeThatFits(CGSizeMake(textView.frame.size.width, CGFloat.max))
        self.frame.size.height = contentSize.height

        if let heightConstraint = self.heightConstraint {
            heightConstraint.constant = self.frame.size.height
        }

        self.textView.reloadInputViews()
    }
}

编辑:这也适用于xib(iOS7/iOS8):

class MessageInputAccessory: UIView, UITextViewDelegate {
    @IBOutlet var textView: UITextView!
    @IBOutlet var textViewHeightConstraint: NSLayoutConstraint!
    private var heightConstraint: NSLayoutConstraint?

    override func awakeFromNib() {
        textView.layer.cornerRadius = 5
        textView.layer.borderWidth = 1
        textView.layer.borderColor = UIColor.blueColor().CGColor
    }

    override func layoutSubviews() {
        textViewHeightConstraint.constant = self.bounds.size.height

        super.layoutSubviews()
    }

    override func addConstraint(constraint: NSLayoutConstraint) {
        if constraint.firstItem === self {
            self.heightConstraint = constraint
        }

        super.addConstraint(constraint)
    }

    override func addConstraints(constraints: [AnyObject]) {
        super.addConstraints(constraints)
    }

    func textViewDidChange(textView: UITextView) {
        var contentSize = textView.sizeThatFits(CGSizeMake(textView.frame.size.width, CGFloat.max))
        self.frame.size.height = contentSize.height

        if let heightConstraint = self.heightConstraint {
            heightConstraint.constant = self.frame.size.height
        }

        self.textView.reloadInputViews()
    }

    override func intrinsicContentSize() -> CGSize {
        return self.bounds.size;
    }
}

有我的xib: 在此处输入图像描述

这不是一个很好的解决方案,但它确实有效。如果您知道更好的方法,请告诉我。

于 2015-05-26T09:19:20.150 回答
2

SWIFT 5解决方案

如果有人像我一样试图在 stackoverflow 中寻找输入附件视图的解决方案,我已经制作了一个简单的项目演示,用于使用 UITextView 动态调整输入附件的大小。它还在 UITextView 顶部带有一个可点击的按钮,以演示在 Input Accessory View 顶部添加的视图。所有这些都加载到 XIB 中以便于定制。用 Swift 5 编写,还负责 X 设备的安全区域。

class InputAccessoryView: UIView, UITextViewDelegate {

@IBOutlet weak var textView: UITextView!

@IBOutlet weak var accessoryButtonViewHeightConstraint: NSLayoutConstraint!

@IBOutlet weak var accessoryButtonView: UIView!
// MARK: - Init

required init?(coder aDecoder: NSCoder) {

    super.init(coder: aDecoder)

    self.setup()
}

override init(frame: CGRect) {

    super.init(frame: frame)

    self.setup()
}

private func setup() {

    let view = self.viewFromNibForClass()

    view?.frame = self.bounds

    view?.autoresizingMask = [.flexibleHeight, .flexibleWidth]

    self.accessoryButtonViewHeightConstraint.constant = 0

    if let view = view {

        self.addSubview(view)

        self.textView.translatesAutoresizingMaskIntoConstraints = false
    }
}

override func didMoveToWindow() {

    super.didMoveToWindow()

    if let window = self.window {

        self.bottomAnchor.constraint(lessThanOrEqualTo: window.safeAreaLayoutGuide.bottomAnchor).isActive = true
    }
}

private func viewFromNibForClass() -> UIView? {

    let bundle = Bundle(for: type(of: self))

    let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)

    let view = nib.instantiate(withOwner: self, options: nil).first as? UIView

    return view
}

func textViewDidChange(_ textView: UITextView) {

    self.accessoryButtonViewHeightConstraint.constant = 40

    self.accessoryButtonView.alpha = 1

    self.updateHeight(textView.contentSize.height + 20 + self.accessoryButtonViewHeightConstraint.constant)
}

private func updateHeight(_ height: CGFloat) {

    for constraint in self.constraints where constraint.firstAttribute == .height {

        constraint.constant = height
    }
}

@IBAction func accessoryButtonTouchUpInside(_ sender: Any) {

    let height = self.frame.size.height - 40

    self.updateHeight(height)

    self.accessoryButtonViewHeightConstraint.constant = 0
}
}

这是一个使用示例: https ://github.com/jaysalvador/InputAccessoryView

于 2019-06-29T03:45:14.913 回答
-1

一个相当简单的解决方法是根本不调整实际 inputAccessoryView 的大小 - 如果您知道它需要的最大高度,您可以在该最大高度创建它,使其透明,然后添加一个调整大小的子视图你喜欢。

您需要使其工作的细节是 inputAccessoryView 需要是包含以下内容的 UIView 子类:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    point = [self.innerView convertPoint:point fromView:self];
    return [self.innerView pointInside:point withEvent:event];
}

(其中 self.innerView 是您动态调整大小的子视图)。

这使得它在子视图内声明水龙头,但传递任何落在它之外的水龙头。

要注意的主要缺点是键盘通知将为您提供包含整个最大高度 inputAccessoryView 的帧。因此,如果您使用它们来(例如)调整插图,您需要在那里做一些额外的数学运算。

于 2016-04-25T01:06:21.537 回答