-
-
Save drewlustro/641d5844e43e87d0c011 to your computer and use it in GitHub Desktop.
// | |
// KeyboardViewController.swift | |
// Demo Custom Keyboard | |
// | |
// Created by Drew Lustro on 10/20/14. | |
// | |
// Original derived from tutorial found on AppDesignVault | |
// http://www.appdesignvault.com/ios-8-custom-keyboard-extension/ | |
// | |
// | |
// *** ALL AUTOLAYOUT CONSTRAINTS HAVE BEEN FIXED! ;) NO MORE WARNINGS | |
// | |
// | |
import UIKit | |
class KeyboardViewController: UIInputViewController { | |
override func updateViewConstraints() { | |
super.updateViewConstraints() | |
// Add custom view sizing constraints here | |
} | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
let buttonTitles1 = ["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"] | |
let buttonTitles2 = ["A", "S", "D", "F", "G", "H", "J", "K", "L"] | |
let buttonTitles3 = ["CP", "Z", "X", "C", "V", "B", "N", "M", "BP"] | |
let buttonTitles4 = ["CHG", "SPACE", "RETURN"] | |
var row1 = createRowOfButtons(buttonTitles1) | |
var row2 = createRowOfButtons(buttonTitles2) | |
var row3 = createRowOfButtons(buttonTitles3) | |
var row4 = createRowOfButtons(buttonTitles4) | |
self.view.addSubview(row1) | |
self.view.addSubview(row2) | |
self.view.addSubview(row3) | |
self.view.addSubview(row4) | |
row1.setTranslatesAutoresizingMaskIntoConstraints(false) | |
row2.setTranslatesAutoresizingMaskIntoConstraints(false) | |
row3.setTranslatesAutoresizingMaskIntoConstraints(false) | |
row4.setTranslatesAutoresizingMaskIntoConstraints(false) | |
addConstraintsToInputView(self.view, rowViews: [row1, row2, row3, row4]) | |
} | |
func createRowOfButtons(buttonTitles: [NSString]) -> UIView { | |
var buttons = [UIButton]() | |
var keyboardRowView = UIView(frame: CGRectMake(0, 0, 320, 50)) | |
keyboardRowView.tag = self.rowCount++ | |
for buttonTitle in buttonTitles { | |
let button = createButtonWithTitle(buttonTitle) | |
buttons.append(button) | |
keyboardRowView.addSubview(button) | |
} | |
addIndividualButtonConstraints(buttons, rowView: keyboardRowView) | |
return keyboardRowView | |
} | |
func createButtonWithTitle(title: String) -> UIButton { | |
let button = UIButton.buttonWithType(.System) as UIButton | |
button.frame = CGRectMake(0, 0, 20, 20) | |
button.setTitle(title, forState: .Normal) | |
button.sizeToFit() | |
button.titleLabel?.font = UIFont.systemFontOfSize(15) | |
button.setTranslatesAutoresizingMaskIntoConstraints(false) | |
button.backgroundColor = UIColor(white: 1.0, alpha: 1.0) | |
button.setTitleColor(UIColor.darkGrayColor(), forState: .Normal) | |
button.addTarget(self, action: "didTapButton:", forControlEvents: .TouchUpInside) | |
return button | |
} | |
func didTapButton(sender: AnyObject?) { | |
let button = sender as UIButton | |
var proxy = textDocumentProxy as UITextDocumentProxy | |
if let title = button.titleForState(.Normal) as String? { | |
switch title { | |
case "BP": | |
proxy.deleteBackward() | |
case "RETURN": | |
proxy.insertText("\n") | |
case "SPACE": | |
proxy.insertText(" ") | |
case "CHG": | |
self.advanceToNextInputMode() | |
default: | |
proxy.insertText(title) | |
} | |
} | |
} | |
override func didReceiveMemoryWarning() { | |
super.didReceiveMemoryWarning() | |
// Dispose of any resources that can be recreated | |
} | |
override func textWillChange(textInput: UITextInput) { | |
// The app is about to change the document's contents. Perform any preparation here. | |
} | |
override func textDidChange(textInput: UITextInput) { | |
// The app has just changed the document's contents, the document context has been updated. | |
var textColor: UIColor | |
var proxy = self.textDocumentProxy as UITextDocumentProxy | |
if proxy.keyboardAppearance == UIKeyboardAppearance.Dark { | |
textColor = UIColor.whiteColor() | |
} else { | |
textColor = UIColor.blackColor() | |
} | |
} | |
func addIndividualButtonConstraints(buttons: [UIButton], rowView: UIView){ | |
for (index, button) in enumerate(buttons) { | |
var topConstraint = NSLayoutConstraint(item: button, attribute: .Top, relatedBy: .LessThanOrEqual, toItem: rowView, attribute: .Top, multiplier: 1.0, constant: 1.0) | |
var bottomConstraint = NSLayoutConstraint(item: button, attribute: .Bottom, relatedBy: .GreaterThanOrEqual, toItem: rowView, attribute: .Bottom, multiplier: 1.0, constant: -1.0) | |
var rightConstraint : NSLayoutConstraint! | |
if index == buttons.count - 1 { | |
rightConstraint = NSLayoutConstraint(item: button, attribute: .Right, relatedBy: .GreaterThanOrEqual, toItem: rowView, attribute: .Right, multiplier: 1.0, constant: 0.0) | |
} else { | |
let nextButton = buttons[index+1] | |
rightConstraint = NSLayoutConstraint(item: button, attribute: .Right, relatedBy: .Equal, toItem: nextButton, attribute: .Left, multiplier: 1.0, constant: -1.0) | |
} | |
var leftConstraint : NSLayoutConstraint! | |
if index == 0 { | |
leftConstraint = NSLayoutConstraint(item: button, attribute: .Left, relatedBy: .LessThanOrEqual, toItem: rowView, attribute: .Left, multiplier: 1.0, constant: 0.0) | |
} else { | |
let prevtButton = buttons[index-1] | |
leftConstraint = NSLayoutConstraint(item: button, attribute: .Left, relatedBy: .Equal, toItem: prevtButton, attribute: .Right, multiplier: 1.0, constant: 1.0) | |
let firstButton = buttons[0] | |
var widthConstraint = NSLayoutConstraint(item: firstButton, attribute: .Width, relatedBy: .Equal, toItem: button, attribute: .Width, multiplier: 1.0, constant: 0.0) | |
widthConstraint.priority = 800.0 | |
rowView.addConstraint(widthConstraint) | |
} | |
rowView.addConstraints([topConstraint, bottomConstraint, rightConstraint, leftConstraint]) | |
} | |
} | |
func addConstraintsToInputView(inputView: UIView, rowViews: [UIView]){ | |
for (index, rowView) in enumerate(rowViews) { | |
var rightSideConstraint = NSLayoutConstraint(item: rowView, attribute: .Right, relatedBy: .Equal, toItem: inputView, attribute: .Right, multiplier: 1.0, constant: 0.0) | |
var leftConstraint = NSLayoutConstraint(item: rowView, attribute: .Left, relatedBy: .Equal, toItem: inputView, attribute: .Left, multiplier: 1.0, constant: 0.0) | |
inputView.addConstraints([leftConstraint, rightSideConstraint]) | |
var topConstraint: NSLayoutConstraint | |
if index == 0 { | |
topConstraint = NSLayoutConstraint(item: rowView, attribute: .Top, relatedBy: .Equal, toItem: inputView, attribute: .Top, multiplier: 1.0, constant: 0.0) | |
} else { | |
let prevRow = rowViews[index-1] | |
topConstraint = NSLayoutConstraint(item: rowView, attribute: .Top, relatedBy: .Equal, toItem: prevRow, attribute: .Bottom, multiplier: 1.0, constant: 0.0) | |
let firstRow = rowViews[0] | |
var heightConstraint = NSLayoutConstraint(item: firstRow, attribute: .Height, relatedBy: .Equal, toItem: rowView, attribute: .Height, multiplier: 1.0, constant: 0.0) | |
heightConstraint.priority = 800.0 | |
inputView.addConstraint(heightConstraint) | |
} | |
inputView.addConstraint(topConstraint) | |
var bottomConstraint: NSLayoutConstraint | |
if index == (rowViews.count - 1) { | |
bottomConstraint = NSLayoutConstraint(item: rowView, attribute: .Bottom, relatedBy: .Equal, toItem: inputView, attribute: .Bottom, multiplier: 1.0, constant: 0.0) | |
} else { | |
let nextRow = rowViews[index+1] | |
bottomConstraint = NSLayoutConstraint(item: rowView, attribute: .Bottom, relatedBy: .Equal, toItem: nextRow, attribute: .Top, multiplier: 1.0, constant: 0.0) | |
} | |
inputView.addConstraint(bottomConstraint) | |
} | |
} | |
} | |
I took this code and made it work for Swift 3.
https://gist.github.com/critical186/4c05e2700fd233507ef1460bd8d969f7
Jared
Just some notes on things that changed
The compiler can correct a lot of the things that changed like .Normal becoming .normal. Here is a list of the items that can not be fixed automatically fixed by the compiler and it took me a long time to figure out the correct way to do it.
Was:
CGRectMake(0, 0, 320, 50)
Is:
CGRect(x:0, y:0, width: 320, height: 50)
Was:
button.setTranslatesAutoresizingMaskIntoConstraints(false)
Is:
button.translatesAutoresizingMaskIntoConstraints = false
Was:
button.addTarget(self, action: "didTapButton:", forControlEvents: .TouchUpInside)
Is:
button.addTarget(self, action:#selector(didTapButton(_:)), for: .touchUpInside)
Was:
for (index, button) in enumerate(buttons) {
}
Is:
for (index, button) in buttons.enumerated() {
}
Hi,
This is SWIFT 1 Style, can you convert it to SWIFT 2 if possible?
Kind regards,
Tony