スポンサーリンク

[SwiftUI]TextEditorにキーボードを閉じる機能と文字数制限をつける

スポンサーリンク

SwiftUIでテキストの入力といえばTextfieldがよく使われていると思いますが、複数行のテキストの入力にはTextEditorが便利です。
iOS14から使えます。

開発環境バージョン
Xcode12.5.1
iOS14.0以降
macOSBigSur 11.5.2
スポンサーリンク

文字数制限付き・キーボードを閉じるボタン付きのTextEditor

TextEditorは複数行の長いテキストを入力できますが、そのままだと文字数制限機能はなく、入力後キーボードを閉じる機能もありません。
(Enterを押してもひたすら改行されるだけで、入力完了できないっていうのは地味に困るのです。)

ということで、200文字まで入力・カウントできて、入力後キーボードを閉じられるテキストボックスを作ってみました。

キーボードを閉じた状態
入力モードになると、キーボードにかぶらないように自動で上にあがる

入力完了を押すとキーボードが閉じます。

//
//  ContentView.swift
//  TextEditorApp
//
//  Created by Yaguchi Sato on 2021/12/10.
//

import SwiftUI

struct ContentView: View {
    @State private var note = ""
//入力文字数
    @State private var totalChars = 0
    @State private var notecount = ""

    var body: some View {
        VStack {
            HStack {
//入力文字数の表示
                Text(" \(totalChars) / 200")
                Spacer()
                            }
            ZStack(alignment: .topLeading ){
//Textの入力 文字カウントと文字数制限付き
                TextEditor(text: $note)
                    .onChange(of: note, perform: {notecount in totalChars = note.count
                    })
                    //200文字以上になったら最後の文字を削除することで制限
                    .onChange(of: note, perform: { value in
                        if value.count > 200 {
                            note.removeLast(note.count - 200)
                        }
                    })
//入力欄の外枠 角丸四角・背景透過・縁枠グレー
                RoundedRectangle(cornerRadius: 8.0)
                    .strokeBorder(Color.gray.opacity(0.5), lineWidth: 0.3).background(Color.clear)
                
            }.frame(height: 300, alignment: .center)

//入力完了ボタンでendEditを呼び出す
            Button(action:{
                UIApplication.shared.endEdit()
            }){Text("入力完了")
                .font(.title)
                .padding(8)
                .foregroundColor(.white)
                .background(Color.orange)
                .cornerRadius(10)
            }

        }.padding()
    }
}

//キーボードを閉じる処理 UIApplicationを拡張
extension UIApplication{
    func endEdit(){
        sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

TextEditorにはTextFieldStyleのように入力枠スタイルの設定項目がないので、自分で角丸四角とZStackで重ねて、.frameでサイズ指定してます。

.onChangeで値の変更を検知。2つ重ねてもちゃんと機能しました。
ちなみに行数制限したい時は、

TextEditor().lineLimit(5)

というように()内に行数上限を指定するとできます。

キーボードを閉じる処理はUIApplicationを利用してます。
そのうちアップデートされる気はしますが、いまのところはこんな感じで対処できました。以上。

タイトルとURLをコピーしました