[译] 用 Swift 创建自定义的键盘
2016-10-19 10:05
302 查看
本文翻译自 How to make a custom keyboard in iOS 8 using Swift
我将讲解一些关于键盘扩展的基本知识,然后使用iOS 8 提供的新应用扩展API来创建一个莫斯码键盘。大概需要你花20多分钟来走完所有的步骤。 完整代码
当用户选择了一个键盘,那么当用户打开一个app时,这个键盘会作为默认的键盘显示。因此这个键盘必须允许用户切换到另一个键盘。
对于每个自定义键盘,有两个开发要素:
信任 : 你的自定义键盘可以访问用户输入的每个字符,所以你和你用户之间的信任非常重要。
下一个键盘按键 : 能够让用户切换另一个键盘这种可见性的功能应该是一个键盘用户界面的一部分;你必须提供这个切换功能。
注意:如果你只需要添加几个按钮到系统的键盘,你应该查看 Custom Views for Data Input
你的自定义键盘不能访问输入视图的层级结构,不能控制光标和选择文本。
另外,自定义键盘无法在顶行以上显示任何东西(如系统键盘,当你在顶行长按一个按键时)。
如何你这么做来申请开放权限,你的键盘会获得一下功能,每一个都伴随着责任:
访问位置服务和 Address BOOK 数据库,在第一次访问时会要求申请用户权限。
可以与包含键盘的app共享一个容器,例如这样可以允许在包含键盘的app里面提供一个自定义的词库管理界面。
能够发送键盘的点击和其它输入事件到服务端去处理。
访问iCloud,例如确保同一个用户的键盘的设置和你的自动更正词库在所有设备上同步。
通过包含键盘的app访问Game Center 和 应用内购买。
如果你设计你的键盘支持手机设备管理(MDM),那么还可以允许与管理的app一起工作。
确保你阅读了 Designing for User Trust ,它描述了在你申请开放权限的情况下,你尊重和保护用户数据的责任。
这个自定义的键盘模版包含一个
[/code]
例如:
把这个文本框居中,添加必要的约束。
暗示: 如果你在
选择
这样就会创建一个新的组,名叫
[/code]
创建一个
[/code]
添加一个
[/code]
使用
在
对于
[/code]
[/code]
[/code]
选择 User Interface 和 View 模版。 命名为
选择 File’s Owner ,改变类名为
在视图中添加一个按钮,设置标题为
[/code]
[/code]
[/code]
最后,代码应该是 这样的 。
选择键盘。
选择添加一个新键盘。找到我们的
现在重新运行我们的应用,尽情享受我们的新键盘吧。
我将讲解一些关于键盘扩展的基本知识,然后使用iOS 8 提供的新应用扩展API来创建一个莫斯码键盘。大概需要你花20多分钟来走完所有的步骤。 完整代码
综述
一个自定义的键盘会替换系统的键盘,来提供给用户一个新的文本输入方法,或者输入哪些iOS系统还不支持的语言。一个自定义键盘的基本功能很简单:响应点击,手势或者其它输入事件以及在当前的文本输入对象的文本插入点上提供非属性化的NSString对象的文本。当用户选择了一个键盘,那么当用户打开一个app时,这个键盘会作为默认的键盘显示。因此这个键盘必须允许用户切换到另一个键盘。
对于每个自定义键盘,有两个开发要素:
信任 : 你的自定义键盘可以访问用户输入的每个字符,所以你和你用户之间的信任非常重要。
下一个键盘按键 : 能够让用户切换另一个键盘这种可见性的功能应该是一个键盘用户界面的一部分;你必须提供这个切换功能。
注意:如果你只需要添加几个按钮到系统的键盘,你应该查看 Custom Views for Data Input
一个自定义键盘不能够做什么
有一些特定的输入对象是你的自定义键盘没资格输入的:安全领域(例如密码输入框), 电话键盘对象(如在通讯录中的电话号码输入框)。你的自定义键盘不能访问输入视图的层级结构,不能控制光标和选择文本。
另外,自定义键盘无法在顶行以上显示任何东西(如系统键盘,当你在顶行长按一个按键时)。
沙盒
默认情况下,一个键盘是没有网络访问权限的,而且也无法与键盘的容器app分享文件。为了获得这些权限,可以在Info.plist 文件中设置RequestsOpenAccess这个布尔类型的键的值为 YES。 做这些会扩展键盘的沙盒,如 Establishing and Maintaining User Trust. 中描述的。
如何你这么做来申请开放权限,你的键盘会获得一下功能,每一个都伴随着责任:
访问位置服务和 Address BOOK 数据库,在第一次访问时会要求申请用户权限。
可以与包含键盘的app共享一个容器,例如这样可以允许在包含键盘的app里面提供一个自定义的词库管理界面。
能够发送键盘的点击和其它输入事件到服务端去处理。
访问iCloud,例如确保同一个用户的键盘的设置和你的自动更正词库在所有设备上同步。
通过包含键盘的app访问Game Center 和 应用内购买。
如果你设计你的键盘支持手机设备管理(MDM),那么还可以允许与管理的app一起工作。
确保你阅读了 Designing for User Trust ,它描述了在你申请开放权限的情况下,你尊重和保护用户数据的责任。
高层视图
下面的图片显示了在一个运行的键盘中一些重要的对象,并且显示了在一个典型的开发流程中这些对象来源于哪里。在一个最基本的形式中,我们有一个app包含了键盘扩展和一个控制这个键盘和响应用户事件的UIInputViewController对象。
这个自定义的键盘模版包含一个
UIInputViewController的子类,这是你的键盘的主视图控制器。让我们看看它的接口是怎么定义的:
class UIInputViewController : UIViewController, UITextInputDelegate, NSObjectProtocol { var inputView: UIInputView! var textDocumentProxy: NSObject! { get } func dismissKeyboard() func advanceToNextInputMode() // This will not provide a complete repository of a language's vocabulary. // It is solely intended to supplement existing lexicons. func requestSupplementaryLexiconWithCompletion(completionHandler: ((UILexicon!) -> Void)!) }
[/code]
inputView是这个键盘的视图,与
view属性一样
dismissKeyboard方法可以被调用来关闭键盘视图
advanceToNextInputMode是用来切换键盘的
textDocumentProxy是你将用来与当前的文本输入进行交互的对象。
例如:
self.textDocumentProxy.insertText("We ❤ Swift") // inserts the string "We ❤ Swift" at the insertion point self.textDocumentProxy.deleteBackward() // Deletes the character to the left of the insertion point
UIInputViewController实现了
UITextInputDelegate协议,当文本或者选择的文本发生变化时,会使用
selectionWillChange,
selectionDidChange,
textWillChange和
textDidChange消息来通知你。
创建一个莫斯码键盘
我们将创建一个简单的键盘,可以输入点和破折号,切换键盘,删除一个字符以及关闭键盘。这个例子只通过代码来创建用户界面。我们也可以使用Nib 文件来创建界面-这个会在教程末尾涉及到。 加载Nibs 文件可能会对性能产生负面影响。创建一个新的工程
打开Xcode 6, 创建一个新的“Single Page Application” 项目,选择 Swift作为开发语言。添加一个text field 文本框
打开Main.storyboard,然后从 Component Library 中拖动一个文本框。我们将在后面使用这个来测试我们的键盘。
把这个文本框居中,添加必要的约束。
暗示: 如果你在
viewDidLoad中调用
textField.becomeFirstResponder()那么当你打开这个app时键盘就会打开。
添加键盘扩展
在navigator中选择项目文件,点击 + 号添加一个新target。选择
Application Extension,使用
Custom Keyboard模版, 命名为
MorseCodeKeyboard。
这样就会创建一个新的组,名叫
MorseCodeKeyboard,里面包含了两个文件
KeyboardViewController.swift和
Info.plist。
清理
打开KeyboardViewController.swift文件。这个模版键盘有一个已经创建好的按钮,用来进行切换键盘的。把这些代码从
viewDidLoad中移到一个新的方法
addNextKeyboardButton中。
func addNextKeyboardButton() { self.nextKeyboardButton = UIButton.buttonWithType(.System) as UIButton ... var nextKeyboardButtonBottomConstraint = NSLayoutConstraint(item: self.nextKeyboardButton, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1.0, constant: -10.0) self.view.addConstraints([nextKeyboardButtonLeftSideConstraint, nextKeyboardButtonBottomConstraint]) }
[/code]
创建一个
addKeyboardButtons方法,然后在
viewDidLoad中调用它。这样会有助于组织代码。现在我们只是有了几个按钮,但是在实际的项目中会有更多的按钮。 在
addKeyboardButtons中调用
addNextKeyboardButton。
class KeyboardViewController: UIInputViewController { ... override func viewDidLoad() { super.viewDidLoad() addKeyboardButtons() } func addKeyboardButtons() { addNextKeyboardButton() } ... }
[/code]
点
现在添加点按钮。 创建一个类型为UIButton!为的
dotButton属性。
class KeyboardViewController: UIInputViewController { var nextKeyboardButton: UIButton! var dotButton: UIButton! ... }
添加一个
addDot方法。 以一个系统类型的按钮来初始化这个
dotButton属性。给
TouchUpInside事件添加一个回调。 设置一个更大的字体和添加一个圆角。 添加约束来把这个按钮放在离水平中心位置左边 50个点,垂直居中的位置。 代码与
nextKeyboardButton的类似。
func addDot() { // initialize the button dotButton = UIButton.buttonWithType(.System) as UIButton dotButton.setTitle(".", forState: .Normal) dotButton.sizeToFit() dotButton.setTranslatesAutoresizingMaskIntoConstraints(false) // adding a callback dotButton.addTarget(self, action: "didTapDot", forControlEvents: .TouchUpInside) // make the font bigger dotButton.titleLabel.font = UIFont.systemFontOfSize(32) // add rounded corners dotButton.backgroundColor = UIColor(white: 0.9, alpha: 1) dotButton.layer.cornerRadius = 5 view.addSubview(dotButton) // makes the vertical centers equa; var dotCenterYConstraint = NSLayoutConstraint(item: dotButton, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1.0, constant: 0) // set the button 50 points to the left (-) of the horizontal center var dotCenterXConstraint = NSLayoutConstraint(item: dotButton, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1.0, constant: -50) view.addConstraints([dotCenterXConstraint, dotCenterYConstraint]) }
[/code]
使用
textDocumentProxy实现
dotButton的回调。
func didTapDot() { var proxy = textDocumentProxy as UITextDocumentProxy proxy.insertText(".") }
在
addKeyboardButtons中调用
addDot。
func addKeyboardButtons() { addDot() addNextKeyboardButton() }
对于
dash,
delete,
hideKeyboard按钮,过程类似。
破折号
代码类似于dotButton,为了把它对称地放在水平中心位置,只需要改变水平约束的常量即可:
func addDash() { ... // set the button 50 points to the left (-) of the horizontal center var dotCenterXConstraint = NSLayoutConstraint(item: dotButton, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1.0, constant: -50) view.addConstraints([dashCenterXConstraint, dashCenterYConstraint]) } func didTapDash() { var proxy = textDocumentProxy as UITextDocumentProxy proxy.insertText("_") }
[/code]
删除按钮
删除按钮会使用deleteBackward方法从
textDocumentProxy中删除一个字符。 这个布局约束与
nextKeyboardButton对称( .Left -> .Right, .Bottom-> .Top)。
func addDelete() { deleteButton = UIButton.buttonWithType(.System) as UIButton deleteButton.setTitle(" Delete ", forState: .Normal) deleteButton.sizeToFit() deleteButton.setTranslatesAutoresizingMaskIntoConstraints(false) deleteButton.addTarget(self, action: "didTapDelete", forControlEvents: .TouchUpInside) deleteButton.backgroundColor = UIColor(white: 0.9, alpha: 1) deleteButton.layer.cornerRadius = 5 view.addSubview(deleteButton) var rightSideConstraint = NSLayoutConstraint(item: deleteButton, attribute: .Right, relatedBy: .Equal, toItem: view, attribute: .Right, multiplier: 1.0, constant: -10.0) var topConstraint = NSLayoutConstraint(item: deleteButton, attribute: .Top, relatedBy: .Equal, toItem: view, attribute: .Top, multiplier: 1.0, constant: +10.0) view.addConstraints([rightSideConstraint, topConstraint]) } func didTapDelete() { var proxy = textDocumentProxy as UITextDocumentProxy proxy.deleteBackward() }
[/code]
隐藏键盘
hideKeyboardButton会在点击时,调用
dismissKeyboard来隐藏键盘:
func addHideKeyboardButton() { hideKeyboardButton = UIButton.buttonWithType(.System) as UIButton hideKeyboardButton.setTitle("Hide Keyboard", forState: .Normal) hideKeyboardButton.sizeToFit() hideKeyboardButton.setTranslatesAutoresizingMaskIntoConstraints(false) hideKeyboardButton.addTarget(self, action: "dismissKeyboard", forControlEvents: .TouchUpInside) view.addSubview(hideKeyboardButton) var rightSideConstraint = NSLayoutConstraint(item: hideKeyboardButton, attribute: .Right, relatedBy: .Equal, toItem: view, attribute: .Right, multiplier: 1.0, constant: -10.0) var bottomConstraint = NSLayoutConstraint(item: hideKeyboardButton, attribute: .Bottom, relatedBy: .Equal, toItem: view, attribute: .Bottom, multiplier: 1.0, constant: -10.0) view.addConstraints([rightSideConstraint, bottomConstraint]) }
[/code]
使用 Nib 文件
为了不用手写这些布局约束,你可以创建一个界面文件,然后直接在上面添加约束。创建一个界面文件
右击MorseCodeKeyboard组,然后选择 New File.
选择 User Interface 和 View 模版。 命名为
CustomKeyboardInterface
选择 File’s Owner ,改变类名为
KeyboardViewController
在视图中添加一个按钮,设置标题为
We ❤ Swift。 界面类似下面这样:
加载界面
在init(nibName, bundle)构造器中加载
CustomKeyboardnib 文件
class KeyboardViewController: UIInputViewController { ... var customInterface: UIView! init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) var nib = UINib(nibName: "CustomKeyBoardInterface", bundle: nil) let objects = nib.instantiateWithOwner(self, options: nil) customInterface = objects[0] as UIView } ... }
[/code]
添加到 inputView
在viewDidLoad方法中,添加自定义的界面到inputView中。
class KeyboardViewController: UIInputViewController { ... override func viewDidLoad() { super.viewDidLoad() view.addSubview(customInterface) ... } ... }
[/code]
给按钮添加一个回调
class KeyboardViewController: UIInputViewController { ... @IBAction func didTapWeheartSwift() { var proxy = textDocumentProxy as UITextDocumentProxy proxy.insertText("We ❤ Swift") } ... }
[/code]
连接按钮的事件到这个回调上
右键这个按钮,然后点击touchUpInside并拖动到
didTapWeHeartSwift这个 IBAction中
最后,代码应该是 这样的 。
在你的设备上安装这个容器app
在你的设备上运行这个app后,如下来添加你的自定义键盘:选择键盘。
选择添加一个新键盘。找到我们的
MorseCode键盘:
现在重新运行我们的应用,尽情享受我们的新键盘吧。
相关文章推荐
- 在iOS8 下用Swift 创建自定义的键盘
- [译] 用 Swift 创建自定义的键盘
- Swift下拉刷新上拉加载更多库,录音和播放功能,自定义的密码键盘,
- Swift类型创建之自定义一个类型详解
- Android创建自定义键盘
- 创建 Swift 自定义集合类
- Android创建自定义系统键盘
- IOS swift 3.0 关于自定义键盘附件关闭虚拟键盘
- Swift 代码创建Plist文件,数据归档(普通数据、自定义对象)
- swift UICollectionView 代码创建 和自定义Cell
- Swift-自定义表情键盘
- Swift-如何自定义键盘(iOS)
- 给Dialog创建自定义键盘popupwindow
- 利用 ASP.NET 2.0 创建自定义 Web 控件
- JSP 最佳实践:为您的JSP标记创建自定义属性
- 创建你的第一个自定义jsp tag(jsp标签)
- 如何创建[圆角、边框色彩渐变、边框宽度自定义]窗体
- 创建自定义的Visual Studio项模板
- 为 ASP.NET Datagrid 创建自定义列