数据input自定义视图的Swift示例(自定义应用程序内键盘)
目标
我想制作一个只在我的应用程序中使用的自定义键盘,而不是需要安装的系统键盘。
我已阅读和尝试
文档
- 应用程序扩展编程指南:自定义键盘
- 数据input的自定义视图
上面的第一篇文章指出:
确保一个自定义的系统范围的键盘确实是你想要开发的。 要为您的应用程序提供完全自定义的键盘,或仅在应用程序中使用自定义键来补充系统键盘,iOS SDK提供了其他更好的选项。 在iOS的文本编程指南中阅读自定义input视图和input用于数据input的自定义视图中的附件视图。
这就是我所说的第二篇文章。 不过,那篇文章没有足够的细节让我开始。
教程
- iOS 8:在Swift中创build自定义键盘
- 如何使用Swift在iOS 8中制作自定义键盘
- Xcode 6教程:iOS 8.0 Swift中简单的自定义键盘
- 使用iOS 8应用程序扩展创build自定义键盘
我可以从上面的列表中的第二个教程中获得一个可用的键盘。 但是,我找不到任何教程展示了如何在数据input自定义视图文档中介绍如何创build应用程序内置键盘。
堆栈溢出
我在回答当前问题的途中也问了(并回答了)这些问题。
- 如何使用应用内自定义键盘的buttoninput文本
- 代表在Swift中
题
有没有人有一个最小的例子(甚至一个button)的应用程序自定义键盘? 我不是在寻找一个完整的教程,只是一个我可以自己展开的概念certificate。
这是一个基本的应用程序内键盘。 同样的方法可以用来做任何键盘布局。 以下是需要做的主要事情:
- 在.xib文件中创build键盘布局,其所有者是包含
UIView
子类的.swift文件。 - 告诉
UITextField
使用自定义键盘。 - 使用委托在键盘和主视图控制器之间进行通信。
创build.xib键盘布局文件
- 在Xcode中,进入文件>新build>文件…> iOS>用户界面>视图来创build.xib文件。
- 我叫我的Keyboard.xib
- 添加你需要的button。
- 使用自动布局约束,以便无论键盘的大小如何,button都会相应地resize。
- 将文件的所有者(而不是根视图)设置为Keyboard.swift文件。 这是一个常见的错误来源。 看最后的说明。
创build.swift UIView子类键盘文件
- 在Xcode转到文件>新build>文件…> iOS>源>cocoa触摸类创build.swift文件。
- 我打电话给我的Keyboard.swift
-
添加下面的代码:
import UIKit // The view controller will adopt this protocol (delegate) // and thus must contain the keyWasTapped method protocol KeyboardDelegate: class { func keyWasTapped(character: String) } class Keyboard: UIView { // This variable will be set as the view controller so that // the keyboard can send messages to the view controller. weak var delegate: KeyboardDelegate? // MARK:- keyboard initialization required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) initializeSubviews() } override init(frame: CGRect) { super.init(frame: frame) initializeSubviews() } func initializeSubviews() { let xibFileName = "Keyboard" // xib extention not included let view = NSBundle.mainBundle().loadNibNamed(xibFileName, owner: self, options: nil)[0] as! UIView self.addSubview(view) view.frame = self.bounds } // MARK:- Button actions from .xib file @IBAction func keyTapped(sender: UIButton) { // When a button is tapped, send that information to the // delegate (ie, the view controller) self.delegate?.keyWasTapped(character: sender.titleLabel!.text!) // could alternatively send a tag value } }
-
控制.xib文件中的button拖动到
@IBAction
文件中的@IBAction
方法,以将它们全部挂钩。 - 请注意协议和委托代码。 看到这个答案是关于代表如何工作的一个简单的解释。
设置视图控制器
- 添加一个
UITextField
到你的主故事板,并用IBOutlet
将它连接到你的视图控制器。 把它叫做textField
。 -
对视图控制器使用以下代码:
import UIKit class ViewController: UIViewController, KeyboardDelegate { @IBOutlet weak var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() // initialize custom keyboard let keyboardView = Keyboard(frame: CGRect(x: 0, y: 0, width: 0, height: 300)) keyboardView.delegate = self // the view controller will be notified by the keyboard whenever a key is tapped // replace system keyboard with custom keyboard textField.inputView = keyboardView } // required method for keyboard delegate protocol func keyWasTapped(character: String) { textField.insertText(character) } }
-
请注意,视图控制器采用我们上面定义的
KeyboardDelegate
协议。
常见错误
如果您收到EXC_BAD_ACCESS错误,可能是因为您将视图的自定义类设置为Keyboard.swift,而不是为nib文件的所有者执行此操作。
selectKeyboard.nib,然后select文件的所有者。
确保根视图的自定义类是空白的。
基于Suragch的回答,我需要一个完成和退格button,如果你是像我这样的noob,那么你可能遇到的一些错误以及我解决它们的方式。
获取EXC_BAD_ACCESS错误? 我包括:
@objc(classname) class classname: UIView{ }
解决了我的问题,但Suragch的更新答案似乎解决这个更合适/正确的方式。
获得SIGABRT错误? 另一个愚蠢的事情是错误地拖动连接,导致SIGABRT错误。 不要从function拖到button,而是将button拖到function上。
添加完成button我将其添加到keyboard.swift中的协议:
protocol KeyboardDelegate: class { func keyWasTapped(character: String) func keyDone() }
然后从我的完成button连接一个新的IBAction到keyboard.swift像这样:
@IBAction func Done(sender: UIButton) { self.delegate?.keyDone() }
然后跳回到我的viewController.swift,我使用这个键盘,并在函数keyWasTapped后添加以下内容:
func keyDone() { view.endEditing(true) }
添加Backspace这让我感到非常沮丧,因为您必须在viewDidLoad()方法中将textField.delegate设置为self(稍后显示)。
首先:在keyboard.swift中添加协议func backspace():
protocol KeyboardDelegate: class { func keyWasTapped(character: String) func keyDone() func backspace() }
第二:连接一个新的IBAction类似于完成操作:
@IBAction func backspace(sender: UIButton) { self.delegate?.backspace() }
第三:到NumberPad出现的viewController.swift。
重要提示:在viewDidLoad()中设置将使用此键盘的所有文本字段。 所以你的viewDidLoad()应该看起来像这样:
override func viewDidLoad() { super.viewDidLoad() self.myTextField1.delegate = self self.myTextField2.delegate = self // initialize custom keyboard let keyboardView = keyboard(frame: CGRect(x: 0, y: 0, width: 0, height: 240)) keyboardView.delegate = self // the view controller will be notified by the keyboard whenever a key is tapped // replace system keyboard with custom keyboard myTextField1.inputView = keyboardView myTextField2.inputView = keyboardView }
我不知道如何,如果有办法只是这样做的视图中的所有textFields。 这将是方便的…
第四:仍然在viewController.swift中,我们需要添加一个variables和两个函数。 它看起来像这样:
var activeTextField = UITextField() func textFieldDidBeginEditing(textField: UITextField) { print("Setting Active Textfield") self.activeTextField = textField print("Active textField Set!") } func backspace() { print("backspaced!") activeTextField.deleteBackward() }
这里发生了什么的解释:
- 你做一个variables,将持有一个textField。
- 当调用“textFieldDidBeginEditing”时,它设置variables,以便知道我们正在处理哪个文本字段。 我添加了很多的打印(),所以我们知道一切正在执行。
- 我们的backspace函数然后检查我们正在处理的textField并使用.deleteBackward()。 这将删除光标前面的直接字符。
你应该做生意。 非常感谢Suragchs帮助我实现这一目标。