質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

6700閲覧

UIPickerViewにDoneボタンを実装し、押下したらPickerが閉じる仕様にしたい。

Risney

総合スコア148

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

1クリップ

投稿2020/08/11 13:01

編集2020/08/12 00:18

前提・実現したいこと

・PickerViewにDoneボタンを実装し、タップしたらPickerが閉じる仕様にしたい
・PickerView以外をタップしたらPickerが閉じる仕様にしたい

現状、
ピッカーを選択したら、
選択したものがラベルに表示されるようになっています。

イメージ説明

該当のソースコード

swift

1import UIKit 2 3class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource { 4 5 @IBOutlet weak var tapLabel: UILabel! 6 @IBOutlet weak var label: UILabel! 7 @IBOutlet weak var pickerView: UIPickerView! 8 9 let dataList = [ 10 "Mickey Mouse","Minnie Mouse","Donald Duck","Goofy","Pluto"] 11 12 override func viewDidLoad() { 13 super.viewDidLoad() 14 // Delegate設定 15 pickerView.delegate = self 16 pickerView.dataSource = self 17 // label初期表示 18 label.text = "Disney\nBig5" 19 // labelの高さを可変にする 20 label.sizeToFit() 21 // pickerを初期表示は隠す 22 pickerView.isHidden = true; 23 24 } 25 26 override func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?){ 27 print("touched") 28 //myLabelはタッチ判定をしたいUILabel 29 if touchedLabel(touches: touches,view:label){ 30 print("PikcerView表示") 31 pickerView.isHidden = false; 32 return 33 } 34 } 35 36 //タッチしたビューと指定したビューが一致した時、trueが返る 37 func touchedLabel(touches: Set<UITouch>, view:UILabel)->Bool{ 38 //全指のタッチについて処理 39 for touch: AnyObject in touches { 40 let t: UITouch = touch as! UITouch 41 if t.view?.tag == view.tag { 42 return true 43 } else { 44 return false 45 } 46 } 47 return false 48 } 49 50 // UIPickerViewの列の数 51 func numberOfComponents(in pickerView: UIPickerView) -> Int { 52 return 1 53 } 54 55 // UIPickerViewの行数、リストの数 56 func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { 57 // dataListの数 58 return dataList.count 59 } 60 61 // UIPickerViewの最初の表示 62 func pickerView(_ pickerView: UIPickerView, 63 titleForRow row: Int, 64 forComponent component: Int) -> String? { 65 return dataList[row] 66 } 67 68 // UIPickerViewのRowが選択された時の挙動 69 func pickerView(_ pickerView: UIPickerView, 70 didSelectRow row: Int, 71 inComponent component: Int) { 72 label.text = dataList[row] 73 } 74 75}

試したこと

以下のサイトでUITextField 入力後に、入力欄外やキーボード以外の画面をタップしてソフトウェアキーボードを非表示にする方法について書いてあったので、それを活用してPickerも可能かと思い、「override func touchesBegan」の中にview.endEditing(true)を書いてみたもののできず。。
【Swift】UITextField入力後に画面をタップしてキーボードを非表示にする

以下のサイトを参考に、
Pickerにボタンを実装しようとしたのですが、
なかなか上手くいかず困っています。。

【swift】UIPickerViewを作ってみる(ドラムロール)
stackoverflow

■追記
ご指示通り修正したものの、何かが指示通りにできていないのかエラーが出てしまいます。
swift

storyboard

error内容:Thread 1: Exception: "-[UILabel setInputView:]: unrecognized selector sent to instance 0x7f9635411bf0"
error

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TsukubaDepot

2020/08/11 13:28

UILabelではなく、UITextField を使い、必要であれば Border Style などを変更することで見た目を Label っぽくすれば、参考にされている記事がそのまま使えますし(入力を PickerView にする、Doneボタンをつける、PickerView 以外をタップすると PickerVierを消す、など)、現在実装されているような Label をタップしたときの処理の実装も不必要になると思いますが、それだと何か不都合があるのでしょうか。
Risney

2020/08/11 22:47 編集

UITextFieldで実装した場合、 UITextFieldをタップした際に、カーソルが表示されてしまうののでLablelで行いたいと思っています。 しかしUILabelで行うことはできないのかと試行錯誤していました… 「試したこと」にも記載の以下のサイトでUITextFieldで実装してみたところ、 UITextFieldタップ後フリーズしてしまい動きませんでした。。 【swift】UIPickerViewを作ってみる(ドラムロール) URL:https://www.egao-inc.co.jp/programming/swift_uipickerview/
guest

回答1

0

ベストアンサー

UITextFieldクラスをカスタムすればカーソル(キャレット)は消すことができるので、以下の様にしたほうがシンプルで良いと思います。

以下の2つのファイルでそのまま動くと思うので、StoryboardViewControllerUITextFiledを乗せ(クラスはカスタムクラスを指定)、IBOutletを結んで試してみてください。

  • ViewController

swift

1import UIKit 2 3class ViewController: UIViewController { 4 5 @IBOutlet weak private var textField: CustomTextField! 6 private let pickerView = UIPickerView(frame: .zero) 7 8 private let dataList = ["Mickey Mouse", "Minnie Mouse", "Donald Duck", "Goofy", "Pluto"] 9 10 override func viewDidLoad() { 11 super.viewDidLoad() 12 textField.text = "Disney\nBig5" 13 setup() 14 } 15 16 private func setup() { 17 pickerView.delegate = self 18 pickerView.dataSource = self 19 let toolbar = UIToolbar() 20 let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) 21 let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(ViewController.tappedDone)) 22 toolbar.items = [space, doneButton] 23 toolbar.sizeToFit() 24 textField.inputView = pickerView 25 textField.inputAccessoryView = toolbar 26 } 27 28 @objc func tappedDone() { 29 textField.resignFirstResponder() 30 } 31} 32 33extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource { 34 func numberOfComponents(in pickerView: UIPickerView) -> Int { 35 return 1 36 } 37 38 func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { 39 return dataList.count 40 } 41 42 func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { 43 return dataList[row] 44 } 45 46 func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { 47 textField.text = dataList[row] 48 } 49}
  • CustomTextField

swift

1import UIKit 2 3final class CustomTextField: UITextField { 4 5 /* 入力キャレット非表示 */ 6 override func caretRect(for position: UITextPosition) -> CGRect { 7 return .zero 8 } 9 /* 範囲選択カーソル非表示 */ 10 override func selectionRects(for range: UITextRange) -> [UITextSelectionRect] { 11 return [] 12 } 13 /* コピー・ペースト・選択等のメニュー非表示 */ 14 override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { 15 return false 16 } 17}

イメージ説明

イメージ説明

投稿2020/08/11 23:51

編集2020/08/12 00:05
_Kentarou

総合スコア8490

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Risney

2020/08/11 23:59

回答ありがとうございます。 初歩的な質問で申し訳ありませんが、 「CustomTextField」は新しくSwiftファイルを追加するという認識で良いでしょうか? その場合は追加したswiftファイルの「import Foundation」以下に 「import UIKit」以降のコードを追加するのでしょうか。
_Kentarou

2020/08/12 00:03

そうですね、新しくファイルを追加してコードを貼り付けてみてください。
Risney

2020/08/12 00:17 編集

ご丁寧に画像つきでありがとうございます。 ご指示通りに試してみたのですが、エラーが出てしまいました。 もう一度自分でも確認してみようと思いますが、 もし心当たりのあればご教授いただければと存じます。 ※追記に画像等を追加いたしました。
_Kentarou

2020/08/12 00:24 編集

UILabelを消してくださいね、IBOutletの接続が残っているかもです。
_Kentarou

2020/08/12 00:21

UITextfieldを配置してそれのCustomClassを変更してください。
Risney

2020/08/12 00:27

ありがとうございます! textFileldに接続しなおしたらクラッシュせずにピッカーも表示されました! しかし一度Doneまたは背景をタップしてピッカーが閉じると、 再度ピッカーを開くことができなくなるのですが、 もう一度出したい場合はどうしたらよいでしょうか。
_Kentarou

2020/08/12 00:28

多分Sotryboardに最初から配置してあるUIViewにCustomTextFieldクラスを設定していると思います。
_Kentarou

2020/08/12 00:29 編集

TextFieldタップでPicker出ないですか?
Risney

2020/08/12 00:39

>多分Sotryboardに最初から配置してあるUIViewにCustomTextFieldクラスを設定していると思います。 この通りでした! >TextFieldタップでPicker出ないですか? 最初しかでなかったのですが、 カスタムクラスの設定を変更したら解決しました! ありがとうございました!
_Kentarou

2020/08/12 00:40

おそらく自分の提示したコードのみにすれば問題ないと思うので(Storyboadの設定も初期値にする)、一旦その状態で問題ないことを確認してから、次の段階へ(背景タップでPickerを閉じる等)進んだほうが原因が分かって良いと思います。
Risney

2020/08/12 00:45

勢いでベストアンサーしてしまいましたが、 背景タップの件が終わってなかったですね。。 でもそれ以外の挙動はKentarouさんのおかげ様で問題なく実装できたので、 次のステップに進みたいと思います!
_Kentarou

2020/08/12 00:51 編集

ちなみに背景タップで閉じるは下のでできます。 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { textField.resignFirstResponder() }
Risney

2020/08/12 01:05

上記のコードで背景タップで閉じました! 何からなにまでありがとうございます! UIDatePickerのほうもこちらを参考にやってみようと思います!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問