在iOS 8中更改inputAccessoryView的框架

Man*_*lla 27 objective-c ios inputaccessoryview ios8

很长一段时间潜伏 - 第一次海报!

我在重建UITextView像WhatsApp这样的酒吧时遇到了问题.

我正在使用自定义UIView子类,并懒惰地实例化它:

- (UIView *)inputAccessoryView

并返回YES:

- (BOOL)canBecomeFirstResponder

现在,我想改变的大小inputAccessoryView时,UITextView在规模的增长.在iOS 7上,我只是改变所述视图框架的大小 - 而不是它的原点 - 然后调用reloadInputViews它会起作用:视图将向上移动,使其在键盘上方完全可见.

但是,在iOS 8上,这不起作用.使其工作的唯一方法是还将帧的原点更改为负值.这样会很好,除了它会产生一些奇怪的错误:例如,UIView在输入任何文本时返回到"原始"框架.

有什么我想念的吗?我非常肯定WhatsApp使用它inputAccessoryView是因为它们在拖动时解除键盘的方式 - 仅在最新版本的应用程序中.

如果你能帮助我,请告诉我!或者,如果有任何测试,您希望我运行!

谢谢!:)

顺便说一下,这是我用来更新自定义UIView高度的代码composeBar:

// ComposeBar frame size
CGRect frame = self.composeBar.frame;
frame.size.height += heightDifference;
frame.origin.y -= heightDifference;
self.composeBar.frame = frame;
[self.composeBar.textView reloadInputViews]; // Tried with this
[self reloadInputViews];                     // and this
Run Code Online (Sandbox Code Playgroud)

编辑:完整源代码可在@ https://github.com/manuelmenzella/SocketChat-iOS获得

Joh*_*nyC 33

由于行为已经从iOS 7改为iOS 8,我已经在这个问题上一直撞到了墙上.我尝试了一切,直到最明显的解决方案为我工作:

inputAccessoryView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
Run Code Online (Sandbox Code Playgroud)

咄!

  • 我将你的建议与 - (CGSize)intrinsicContentSize结合使用,现在它可以工作了.只有那行代码不起作用. (6认同)
  • 然后在进行更改后在附件视图上调用-invalidateIntrinsicContentSize. (3认同)

max*_*lov 17

总结一下JohnnyC的答案:将你的inpitAccessoryView设置autoresizingMask.flexibleHeight,计算它intrinsicContentSize并让框架完成剩下的工作.

完整代码,针对Swift 3进行了更新:

class InputAccessoryView: UIView, UITextViewDelegate {

    let textView = UITextView()

    override var intrinsicContentSize: CGSize {
        // Calculate intrinsicContentSize that will fit all the text
        let textSize = textView.sizeThatFits(CGSize(width: textView.bounds.width, height: CGFloat.greatestFiniteMagnitude))
        return CGSize(width: bounds.width, height: textSize.height)
    }

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

        // This is required to make the view grow vertically
        autoresizingMask = .flexibleHeight

        // Setup textView as needed
        addSubview(textView)
        textView.translatesAutoresizingMaskIntoConstraints = false
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[textView]|", options: [], metrics: nil, views: ["textView": textView]))
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[textView]|", options: [], metrics: nil, views: ["textView": textView]))

        textView.delegate = self

        // Disabling textView scrolling prevents some undesired effects,
        // like incorrect contentOffset when adding new line,
        // and makes the textView behave similar to Apple's Messages app
        textView.isScrollEnabled = false
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // MARK: UITextViewDelegate

    func textViewDidChange(_ textView: UITextView) {
        // Re-calculate intrinsicContentSize when text changes
        invalidateIntrinsicContentSize()
    }

}
Run Code Online (Sandbox Code Playgroud)


Rah*_*swa 5

问题是在iOS 8中,自动安装了一个NSLayoutConstraint,它将inputAccessoryView的高度设置为等于其初始帧高.为了解决布局问题,您需要将该约束更新为所需的高度,然后指示您的inputAccessoryView自行布局.

- (void)changeInputAccessoryView:(UIView *)inputAccessoryView toHeight:(CGFloat)height {
    for (NSLayoutConstraint *constraint in [inputAccessoryView constraints]) {
        if (constraint.firstAttribute == NSLayoutAttributeHeight) {
            constraint.constant = height;
            [inputAccessoryView layoutIfNeeded];
            break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


And*_*nko 5

下面是一个完整,独立的解决方案(感谢@JohnnyC@JoãoNunes指着我在正确的方向,@stigi用于解释如何制作动画intrinsicContent的变化):

class InputAccessoryView: UIView {

    // InputAccessoryView is instantiated from nib, but it's not a requirement
    override func awakeFromNib() {
        super.awakeFromNib()        
        autoresizingMask = .FlexibleHeight
    }

    override func intrinsicContentSize() -> CGSize {
        let exactHeight = // calculate exact height of your view here
        return CGSize(width: UIViewNoIntrinsicMetric, height: exactHeight)
    }

    func somethingDidHappen() {
        // invalidate intrinsic content size, animate superview layout        
        UIView.animateWithDuration(0.2) {
            self.invalidateIntrinsicContentSize()
            self.superview?.setNeedsLayout()
            self.superview?.layoutIfNeeded()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)