Custom Keyboard Extension 的屁事博 -- 在Container App 中植入键盘(二)

开始着手现有输入法植入工作,亟待解决的问题有下面几个:

  1. 系统调用输入法时KeyboardViewController如何加载
  2. 能否(如何)将KeyboardViewController的视图加载到应用程序的视图控制器
  3. Keyboard如何(是否需要)与输入框进行关联

下面来一一解决:

系统调用键盘

上一张经典图

关于ExtensionContainer AppHost App这三者的关系这里不再赘述,网上很多资料。这里体现了一件事情就是:系统在调用键盘时,Keyboard是没有加载在应用程序keyWindow中的,而是在一个新的名叫UIRemoteKeyboardWindow的窗口中

系统日语输入法在App中加载

应用程序视图中加载键盘

在以前的项目中,当我们希望系统弹出键盘时一般使用textField.becomeFirstResponder()这样的方法,让输入框成为第一响应者来实现。现在我们需要的是指定一个我们项目中已经实现过的KeyboardViewController来弹出,而不是通过系统调用键盘,然后让用户切换过去。

调查过后锁定了几个东西:UITextField.inputViewUIResponder.inputViewController
实验发现,不论是设置inputViewKeyboardViewControllerview或者是重载UITextFieldinputViewController设置为KeyboardViewController都可以实现在UIRemoteKeyboardWindow窗口中调起该键盘。

但这样调起的键盘无法在画面中获得,也无法设置画面约束等,仅仅是一个调起指定实现的键盘的方法,局限性太大。

既然KeyboardViewController的父类UIInputViewController是基于UIViewController的,那么我们能不能直接将它作为子VC并将视图加入应用程序视图中呢?

好像没啥问题

最简单实现childViewController的方法就是直接使用storyboard中的Container View。拖上容器,设置约束,将子VC类型设置为我们的KeyboardViewController,直接运行,键盘就躺在画面中等着我们了。

关联输入框

这时候,点击输入框,诶?

怎么又弹出一个新键盘出来了,先不管,点击收起弹出来的键盘,在我们的子VC的键盘上操作,诶?好像可以直接输入到输入框上?!似乎:加载在视图中的UIInputView,输出文字会自动输入到当前的FirstResponder中,而不用做其他关联

这似乎是一个比较好的实现,不过我们还得解决一下输入框获得焦点时系统弹出键盘的问题。这时,我们的inputView

1
textField.inputView = UIView()

或者直接重载inputViewControllerinputView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
extension UITextField {
//重载应用中所有textField的inputViewController
open override var inputViewController: UIInputViewController?{
get{
return UIInputViewController()
}
}
}
class MyTextField: UITextField {
lazy var emptyInputView = UIView()
//重载inputView
override var inputView: UIView? {
set{
}
get{
return emptyInputView
}
}
}

完美√