この記事は 2022 年 03 月 15 日に投稿しました。
目次
AC
リンク
1. はじめに
こんにちは、iOS のエディタアプリPWEditorの開発者の二俣です。
今回は業務で使用している SwiftUIのTextViewでキーボードを閉じる方法についてです。
2. SwiftUIのTextViewでキーボードを閉じる
SwiftUIのTextViewでキーボードを閉じるには、以下の様な実装にします。
実装例
※【SwiftUI】UIViewRepresentableでTextViewを作るを参考にしました。
InputAccessoryView.swift
import UIKit class InputAccessoryView: UIView { private static let ToolbarHeight: CGFloat = 44.0 private(set) var toolbar: UIToolbar! private var leftConstraint: NSLayoutConstraint? = nil private var rightConstraint: NSLayoutConstraint? = nil override var intrinsicContentSize: CGSize { var size = bounds.size size.height = InputAccessoryView.ToolbarHeight + safeAreaInsets.bottom return size } required init?(coder: NSCoder) { super.init(coder: coder) initialize() } init() { super.init(frame: .zero) initialize() } override init(frame: CGRect) { super.init(frame: frame) initialize() } private func initialize() { toolbar = UIToolbar() addSubview(toolbar) toolbar.translatesAutoresizingMaskIntoConstraints = false toolbar.topAnchor.constraint(equalTo: self.topAnchor).isActive = true toolbar.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true toolbar.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true toolbar.heightAnchor.constraint(equalToConstant: InputAccessoryView.ToolbarHeight).isActive = true translatesAutoresizingMaskIntoConstraints = false } override func safeAreaInsetsDidChange() { super.safeAreaInsetsDidChange() invalidateIntrinsicContentSize() setNeedsUpdateConstraints() } override func removeFromSuperview() { super.removeFromSuperview() leftConstraint?.isActive = false leftConstraint = nil rightConstraint?.isActive = false rightConstraint = nil } override func didMoveToSuperview() { super.didMoveToSuperview() if let superview = superview { leftConstraint?.isActive = false leftConstraint = self.leftAnchor.constraint(equalTo: superview.leftAnchor) leftConstraint!.isActive = true rightConstraint?.isActive = false rightConstraint = self.rightAnchor.constraint(equalTo: superview.rightAnchor) rightConstraint!.isActive = true } } }
ContentView.swift
import SwiftUI struct TextView: UIViewRepresentable { @Binding var text: String func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIView(context: Context) -> UITextView { let textView = UITextView() textView.delegate = context.coordinator textView.isScrollEnabled = true textView.isEditable = true textView.isUserInteractionEnabled = true textView.setInputAccessoryView() return textView } func updateUIView(_ textView: UITextView, context: Context) { textView.text = text } } extension TextView { final class Coordinator: NSObject, UITextViewDelegate { private var textView: TextView init(_ textView: TextView) { self.textView = textView } func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { return true } func textViewDidChange(_ textView: UITextView) { self.textView.text = textView.text } } } extension UITextView { func setInputAccessoryView() { let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let closeButton = UIBarButtonItem(image: UIImage(systemName: "xmark"), style: .plain, target: self, action: #selector(tapDoneButton(sender:))) let inputAccessoryView = InputAccessoryView() let items = [spacer, closeButton] inputAccessoryView.toolbar.setItems(items, animated: false) inputAccessoryView.toolbar.updateConstraintsIfNeeded() self.inputAccessoryView = inputAccessoryView } @objc private func tapDoneButton(sender: UIButton) { self.endEditing(true) } } struct ContentView: View { @State private var text = "" var body: some View { TextView(text: $text) } }
実行結果
キーボード表示時
キーボードを閉じた後
リファレンス
3. おわりに
前回
でSwiftUIでUITextViewを使用する方法を紹介しました。
しかし相変わらずキーボードを閉じる術がないので、その方法を調べました。
リンク
紹介している一部の記事のコードはGitlabで公開しています。
興味のある方は覗いてみてください。
私が勤務しているニューラルでは、主に組み込み系ソフトの開発を行っております。
弊社製品のハイブリッド OS Bi-OSは高い技術力を評価されており、特に制御系や通信系を得意としています。
私自身はiOS モバイルアプリやウィンドウズアプリを得意としております。
ソフトウェア開発に関して相談などございましたら、お気軽にご連絡ください。
また一緒に働きたい技術者の方も随時募集中です。
興味がありましたらご連絡ください。
EMAIL : info-nr@newral.co.jp / m-futamata@newral.co.jp
TEL : 042-523-3663
FAX : 042-540-1688