我使用inputView为UITextField设置了自定义键盘。我可以再次切换到原生键盘,此时键盘的高度可以改变(例如,在自动提示上向上/向下滑动,更换键盘)。这就是为什么我的自定义键盘inputView需要能够改变它的高度。
但是,当inputView的帧高度发生变化时,它会再次神奇地重置自己!
(我在iOS 8.4模拟器上这样做。)
将问题简化为最基本的例子:
func createInputView(#height:CGFloat) -> UIView {
let view = ViewSubclass(frame: CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), height))
view.backgroundColor = UIColor.redColor()
let label = UILabel(frame: CGRectMake(0, 0, 100, 30))
label.backgroundColor = UIColor.yellowColor()
label.text = "Hello!"
view.addSubview(label)
return view
}
// halves the view's frame height
func changeFrameHeightForView(view: UIView) {
view.frame = {
var f = view.frame
f.size.height = f.size.height / 2.0
return f
}()
}
override func viewDidLoad() {
super.viewDidLoad()
view1 = createInputView(height: 200)
view2 = createInputView(height: 150)
myTextField.inputView = view1
}
// to reproduce this scenario, you would first focus on the text field to open the keyboard, and then tap on the controller's view, which triggers the below action:
// example 1
@IBAction func viewTapped(sender: AnyObject) {
let currentInputView = self.myTextField.inputView!
println("starting height: \(currentInputView.frame.height)")
// starting height: 200.0
changeFrameHeightForView(currentInputView)
println("height after frame changed: \(currentInputView.frame.height)")
// height after frame changed: 100.0
self.myTextField.reloadInputViews()
println("height after reloadInputViews: \(currentInputView.frame.height)")
// height after reloadInputViews: 100.0
// if I stopped here, the view will update and be shorter, but it shows a grey area underneath - the keyboard itself hasn't changed height! So try to dismiss the keyboard and reload it again...
myTextField.resignFirstResponder()
println("height after resign first responder: \(currentInputView.frame.height)")
// height after resign first responder: 200.0 // --> HOW DID IT GET REVERTED???
myTextField.becomeFirstResponder()
println("height after become first responder: \(currentInputView.frame.height)")
// height after become first responder: 200.0
}
因此,例1的问题是: 为什么一旦调用resignFirstResponder就会恢复帧?
我开始思考,也许文本字段正在对inputView做一些事情。那么如果我把它弄清楚怎么办?那么它应该不能影响原始视图吧?这就是它变得奇怪的地方......
// example 2
@IBAction func viewTapped(sender: AnyObject) {
let currentInputView = self.myTextField.inputView!
println("starting height: \(currentInputView.frame.height)")
// starting height: 200.0
// remove the inputView and close the keyboard.
self.myTextField.inputView = nil
self.myTextField.reloadInputViews()
myTextField.resignFirstResponder()
// change the frame height
changeFrameHeightForView(currentInputView)
println("height after frame changed: \(currentInputView.frame.height)")
// height after frame changed: 100.0
// set it as the inputView again
self.myTextField.inputView = currentInputView
self.myTextField.reloadInputViews()
println("height after reloadInputViews: \(currentInputView.frame.height)")
// height after reloadInputViews: 100.0
// open the keyboard
myTextField.becomeFirstResponder()
println("height after become first responder: \(currentInputView.frame.height)")
// height after become first responder: 200.0 // --> HOW DID IT GET REVERTED??? Shouldn't the keyboard use the new frame height?
}
转到示例3 ...... 那些敏锐的眼睛会注意到我有2个输入视图设置。在这里,我将在它们之间切换inputView。有趣的是,如果分配了不同的视图对象,它将按预期工作:
// example 3
@IBAction func viewTapped(sender: AnyObject) {
let currentInputView = self.myTextField.inputView!
let otherView = (currentInputView == self.view1 ? self.view2 : self.view1)
self.myTextField.inputView = otherView
self.myTextField.reloadInputViews()
}
对于长期问题道歉,但我在本次调查中记录了我的发现。每次键盘改变高度时,我都不想创建一个全新的视图。
Facebook messenger的自定义键盘可以做类似的事情,所以我希望有人可以对此有所了解。
谢谢!