UIViewでテキスト入力を行う(UIKeyInput)
前回の記事の続きです。
前回のテキストを描画した画面に、キーボードからテキストを入力を行う方法についてまとめます。今回も前回と同様にSwiftUI + CoreText (CoreTextSwift) を利用します。
テキスト入力
テキストを入力するには、キャレットの表示や文字を挿入できるようにする必要があります。
UIKeyInputプロトコルを実装すると、システムキーボードを表示させ文字入力を行えるようになります。
また、日本語など入力するにはIME APIを通してやり取りできる必要があります。そのためにはUITextInputプロトコルを実装します。
UIKeyInputの実装
UITextInputは実装すべきメソッドが多く実装が複雑になるため、ひとまず簡単なテキスト入力だけ行えるように、UIKeyInputプロトコルを実装します。
今回はtextが可変となるため、Bindingの変数textを受け取るようにします。
struct ContentView: View {
@State private var text = ""
var body: some View {
VStack() {
CoreTextView(text: $text)
}
}
}
UIViewRepresentableは前回とほぼ同様ですが、becomeFirstResponder()を呼び出すようにしています。これによりファーストレスポンダとしてテキスト入力を処理できるようになります。
struct CoreTextView: UIViewRepresentable {
@Binding var text: String
func makeUIView(context: Context) -> UICoreTextView {
let view = UICoreTextView(text: $text)
view.becomeFirstResponder()
view.isOpaque = false
return view
}
func updateUIView(_ uiView: UICoreTextView, context: Context) {
}
}
前回のUICoreTextViewがBinding変数textを保持できるようにします。今回はdidSetで変数が変更されるたびにsetNeedsDisplay()を呼び出すようにします。
また、上記で設定したbecomeFirstResponder()が有効になるように、canBecomeFirstResponderとcanResignFirstResponderをtrueに設定します。
class UICoreTextView: UIView {
@Binding var text: String {
didSet {
self.setNeedsDisplay()
}
}
init(text: Binding<String>) {
self._text = text
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
fatalError()
}
override func draw(_ rect: CGRect) {
// 前回と同じのため省略
}
override var canBecomeFirstResponder: Bool {
return true
}
override var canResignFirstResponder: Bool {
return true
}
}
次にUIKeyInputを実装します。
extension UICoreTextView: UIKeyInput {
var hasText: Bool {
return self.text.count > 0
}
func insertText(_ text: String) {
self.text.append(text)
}
func deleteBackward() {
if self.text.count > 0 {
self.text.removeLast()
}
}
}
これにより基本的なテキスト入力ができるようになりました。
参考
参考1: Lower Level Text-Handling Technologies
参考2: UIViewとUITextInputで作る縦書きのTextView iOSDC Japan 2018
今回、記載しなかったUITextInputの実装は以下のコード(リポジトリ)が参考になりそうです。
最後まで読んでいただきありがとうございます。 他の記事はこちらからどうぞ → https://note.com/sat0b3ee/