在iOS8 下用Swift 创建自定义的键盘
本文翻譯自How to make a custom keyboard in iOS 8 using Swift
我將講解一些關于鍵盤擴展的基本知識,然后使用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)!) }inputView 是這個鍵盤的視圖,與view屬性一樣
dismissKeyboard方法可以被調用來關閉鍵盤視圖
advanceToNextInputMode 是用來切換鍵盤的
textDocumentProxy 是你將用來與當前的文本輸入進行交互的對象。
例如:
self.textDocumentProxy.insertText("We ? Swift") // inserts the string "We ? Swift" at the insertion pointself.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]) }創建一個 addKeyboardButtons 方法,然后在 viewDidLoad 中調用它。這樣會有助于組織代碼。現在我們只是有了幾個按鈕,但是在實際的項目中會有更多的按鈕。 在 addKeyboardButtons 中調用 addNextKeyboardButton 。
class KeyboardViewController: UIInputViewController {...override func viewDidLoad() {super.viewDidLoad()addKeyboardButtons()}func addKeyboardButtons() {addNextKeyboardButton()}...}點
現在添加點按鈕。 創建一個類型為 UIButton! 為的 dotButton 屬性。
class KeyboardViewController: UIInputViewController {var nextKeyboardButton: UIButton!var dotButton: UIButton!... }添加一個 addDot 方法。 以一個系統類型的按鈕來初始化這個 dotButton 屬性。給 TouchUpInside 事件添加一個回調。 設置一個更大的字體和添加一個圓角。 添加約束來把這個按鈕放在離水平中心位置左邊 50個點,垂直居中的位置。 代碼與 nextKeyboardButton 的類似。
func addDot() {// initialize the buttondotButton = UIButton.buttonWithType(.System) as UIButtondotButton.setTitle(".", forState: .Normal)dotButton.sizeToFit()dotButton.setTranslatesAutoresizingMaskIntoConstraints(false)// adding a callbackdotButton.addTarget(self, action: "didTapDot", forControlEvents: .TouchUpInside)// make the font biggerdotButton.titleLabel.font = UIFont.systemFontOfSize(32)// add rounded cornersdotButton.backgroundColor = UIColor(white: 0.9, alpha: 1)dotButton.layer.cornerRadius = 5view.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 centervar dotCenterXConstraint = NSLayoutConstraint(item: dotButton, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1.0, constant: -50)view.addConstraints([dotCenterXConstraint, dotCenterYConstraint]) }使用 textDocumentProxy實現 dotButton 的回調。
func didTapDot() {var proxy = textDocumentProxy as UITextDocumentProxyproxy.insertText(".") }在 addKeyboardButtons 中調用 addDot。
func addKeyboardButtons() {addDot()addNextKeyboardButton() }對于 dash,delete, hideKeyboard 按鈕,過程類似。
破折號
代碼類似于 dotButton,為了把它對稱地放在水平中心位置,只需要改變水平約束的常量即可:
func addDash() {...// set the button 50 points to the left (-) of the horizontal centervar 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 UITextDocumentProxyproxy.insertText("_") }刪除按鈕
刪除按鈕會使用 deleteBackward 方法從 textDocumentProxy 中刪除一個字符。 這個布局約束與 nextKeyboardButton 對稱( .Left -> .Right, .Bottom-> .Top)。
func addDelete() {deleteButton = UIButton.buttonWithType(.System) as UIButtondeleteButton.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 = 5view.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 UITextDocumentProxyproxy.deleteBackward() }隱藏鍵盤
hideKeyboardButton 會在點擊時,調用 dismissKeyboard 來隱藏鍵盤:
func addHideKeyboardButton() {hideKeyboardButton = UIButton.buttonWithType(.System) as UIButtonhideKeyboardButton.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]) }使用 Nib 文件
為了不用手寫這些布局約束,你可以創建一個界面文件,然后直接在上面添加約束。
創建一個界面文件
右擊 MorseCodeKeyboard組,然后選擇 New File.
選擇 User Interface 和 View 模版。 命名為 CustomKeyboardInterface
選擇 File's Owner ,改變類名為 KeyboardViewController
在視圖中添加一個按鈕,設置標題為 We ? Swift 。 界面類似下面這樣:
加載界面
在 init(nibName, bundle) 構造器中加載 CustomKeyboard nib 文件
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}...}添加到 inputView
在 viewDidLoad 方法中,添加自定義的界面到inputView中。
class KeyboardViewController: UIInputViewController {...override func viewDidLoad() {super.viewDidLoad()view.addSubview(customInterface)...}... }給按鈕添加一個回調
class KeyboardViewController: UIInputViewController {...@IBAction func didTapWeheartSwift() {var proxy = textDocumentProxy as UITextDocumentProxyproxy.insertText("We ? Swift")}... }連接按鈕的事件到這個回調上
右鍵這個按鈕,然后點擊 touchUpInside 并拖動到 didTapWeHeartSwift 這個 IBAction中
最后,代碼應該是這樣的。
在你的設備上安裝這個容器app
在你的設備上運行這個app后,如下來添加你的自定義鍵盤:
選擇鍵盤。
選擇添加一個新鍵盤。找到我們的 MorseCode鍵盤:
現在重新運行我們的應用,盡情享受我們的新鍵盤吧。
轉載于:https://www.cnblogs.com/YungMing/p/4492869.html
總結
以上是生活随笔為你收集整理的在iOS8 下用Swift 创建自定义的键盘的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 选择让孩子练习羽毛球的家长好好看看!
- 下一篇: [裴礼文数学分析中的典型问题与方法习题参