【SwiftUI】

お手軽にTextFieldにキーボードのPickerで入力する方法

TextFieldへPickerで入力

投稿日 2021/04/06 更新日 2021/09/26


こんにちは。当サイトの管理者「元木皇天」です。

今回はSwiftUIでUIkitを使用せずに、「TextFieldにキーボードのような感じ」のPickerで入力する方法について解説します。

環境
OS:MacOS Big Sur
Xcode:バージョン12.3
Swift:バージョン5.3

参考文献:詳細! SwiftUI iPhoneアプリ開発入門ノート[2020] iOS 14+Xcode 12対応

やりたいこと

UIkitを使用せずに、TextFieldの入力キーボードにPickerを設定して、値を入力できるようにする。

(管理人はUIkitを使用するのがめんどくさいので、本記事を作成しました。)

実装方法の解説

はじめにどのように実装するかを解説します。

難しいことは考えなくて大丈夫です。

(ちなみに今回はTextFieldも使用しません。あくまでTextField風です。)


1.Pickerのみのviewを作成
2.入力欄をタップした時に1のviewを下から画面1/4くらいまで表示する

これだけです!

画面を作って、それを別の画面で呼び出して表示するだけです。

入力値は@Bindingと@Stateを使用して連携します。入力欄はTextFieldを使用すると普通のキーボードが出てしまうため、TextFieldのような見た目のHStackとTextを作成します。

これでできるんです!

難しいと思わず試しに実装していただけたらとても嬉しいです。

Pickerだけのviewの作成

まずはPickerだけが表示されるviewを作成します。

今回はContentView内に作成していきます。コードは以下の通りです。

import SwiftUI

//ユーザを入力するキーボード
struct playerPicker: View {
    @Binding  var selectUser: String
    @Binding  var showPicker: Bool

    var body: some View {
        VStack(){
            HStack(){
                //ユーザを入力するピッカー
                Picker(selection: self.$selectUser, label: Text("")) {
                    Text("User1").tag("User1")
                    Text("User2").tag("User2")
                    Text("User3").tag("User3")
                }
            }
        }
    }
}

なんの変哲もないPickerを持つViewを作成しました。

ここで用意している変数「selectUser」はPickerで選択したユーザ名を保存しておく変数です。

showPicker」はPickerの表示・非表示を切り替える変数です。trueで表示させます。

この時点での実際のコードとアプリの画面は以下の通りです。

Pickerを作成した時点の画面 コードの全体

まだPickerのViewを表示する処理を記載していないため、Hello Worldしか表示されていません。

入力欄タップ時にPickerを表示

今の状態ではPickerが表示されないので、TextField風の入力欄をタップした際にPickerが表示されるような処理を記載します。

入力欄は見た目をTextFieldそっくりにしたButtonを使用します。

以下がそのボタンを実装したコードです。

import SwiftUI

struct ContentView: View {

    @State  var selectUser: String = ""
    @State  var showPicker: Bool = false

    var body : some View {

        VStack(){
            Spacer()

            Button(action: {
                //Pickerの表示・非表示を切り替える
                self.showPicker.toggle()
            }) {
                HStack(){
                    Spacer()
                    Text(selectUser)
                        .padding()
                    Spacer()
                }
                .border(Color(red: 220/255, green: 220/255, blue: 220/255, opacity: 1.0), width: 1.5)
                .cornerRadius(3)
                .padding()
            }

            Spacer()
        }

        playerPicker(selectUser: self.$selectUser, showPicker: self.$showPicker)
                        .animation(.linear)
                        .offset(y: self.showPicker ? 0 : UIScreen.main.bounds.height)
    }
}

ContentViewの中にボタンを配置しました。そしてその下にPickerのみのViewを配置しています。

.offset()に記載している内容としては、Pickerが表示された時に画面に表示する高さを設定しています。

これで、入力欄をタップすると、画面下からシュッとPickerが表示されます。

この状態だと、Pickerを閉じるためにもう一度ボタンをタップする必要があり、キーボード風としてはいまいちです。 ですので、画面の閉じるボタンを次に作成していきたいと思います。

ここまでの実際のコードと画面の動きは以下のようになっています。

コード全体の画像

閉じるボタンをつける

それっぽくなってきたところで、キーボード風のPickerを閉じるためのボタンを配置します。

作り方はいたって簡単です。下から出てくるPickerのViewの表示を切り替えるBool型の変数を、タップするとfalseにする処理を書くだけです。

以下が、PickerのViewに閉じるボタンを実装したコードです。

import SwiftUI

//省略

//ユーザを入力するキーボード
struct playerPicker: View {
    @Binding  var selectUser: String
    @Binding  var showPicker: Bool

    var body: some View {
        VStack(){
            //閉じるボタン
            Button(action: {
                self.showPicker = false
            }) {
                HStack {
                    Spacer() //右寄せにするため使用
                    Text("完了")
                        .padding(.horizontal, 15.0)
                }
            }

            HStack(){
                //ユーザを入力するピッカー
                Picker(selection: self.$selectUser, label: Text("")) {
                    Text("User1").tag("User1")
                    Text("User2").tag("User2")
                    Text("User3").tag("User3")
                }
            }
        }
    }
}

これで機能としては完成です。最後に見た目を整えましょう。ここまでの実際の画面の動きとコードは以下になります。

コード全体の画像

見た目を整える

それでは最後に見た目を整えていきましょう。(見た目を気にしない人はここは読み飛ばしていただいて大丈夫です。)

見た目を変更するのは、入力した文字の色とキーボード風のPickerです。

以下が見た目を整えたコードです。

import SwiftUI

struct ContentView: View {

    //省略

    var body : some View {

        VStack(){
            Spacer()

            Button(action: {
                //省略
            }) {
                HStack(){
                    Spacer()
                    Text(selectUser)
                        .padding()
                        .foregroundColor(.black)
                    Spacer()
                }
                //省略
            }

            Spacer()
        }
        //省略
    }
}

//ユーザを入力するキーボード
struct playerPicker: View {
    //省略
    var body: some View {
        VStack(){
            //閉じるボタン
            Button(action: {
                self.showPicker = false
            }) {
                HStack {
                    Spacer() //右寄せにするため使用
                    Text("完了")
                        .padding(.horizontal, 15.0)
                }
            }
            .padding(.vertical, 10.0)
            .background(Color(red: 238/255, green: 238/255, blue: 238/255, opacity: 1.0))

            HStack(){
                //省略
            }
        }
    }
}

微調整を終えたところで、完成です。全コードと最終完成の画面は次のまとめの項目に記載していますのでご参考にしてください。

まとめ

いかがだったでしょうか?

やりようによっては、わざわざUIkitを使用せずとも、SwiftUIの機能だけで実装でき流ことがわかりました。

最後に、ここで作成した実際の画面の動きと、コードを記載しておきます。

ありがとうございました。

import SwiftUI

struct ContentView: View {

    @State  var selectUser: String = ""
    @State  var showPicker: Bool = false

    var body : some View {

        VStack(){
            Spacer()

            Button(action: {
                //Pickerの表示・非表示を切り替える
                self.showPicker.toggle()
            }) {
                HStack(){
                    Spacer()
                    Text(selectUser)
                        .padding()
                        .foregroundColor(.black)
                    Spacer()
                }
                .border(Color(red: 220/255, green: 220/255, blue: 220/255, opacity: 1.0), width: 1.5)
                .cornerRadius(3)
                .padding()
            }

            Spacer()
        }

        playerPicker(selectUser: self.$selectUser, showPicker: self.$showPicker)
                        .animation(.linear)
                        .offset(y: self.showPicker ? 0 : UIScreen.main.bounds.height)

    }
}

//ユーザを入力するキーボード
struct playerPicker: View {
    @Binding  var selectUser: String
    @Binding  var showPicker: Bool

    var body: some View {
        VStack(){
            //閉じるボタン
            Button(action: {
                self.showPicker = false
            }) {
                HStack {
                    Spacer() //右寄せにするため使用
                    Text("完了")
                        .padding(.horizontal, 15.0)
                }
            }
            .padding(.vertical, 10.0)
            .background(Color(red: 238/255, green: 238/255, blue: 238/255, opacity: 1.0))

            HStack(){
                //ユーザを入力するピッカー
                Picker(selection: self.$selectUser, label: Text("")) {
                    Text("User1").tag("User1")
                    Text("User2").tag("User2")
                    Text("User3").tag("User3")
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

参考文献・おすすめ文献