【Swift】Picker Viewを使って、秒も設定できるカウントダウンタイマーを作る。(Swift 2.1、XCode 7.2)
秒も設定できるカウントダウンタイマー
前回までの記事で、ホイールを回してデータを選択するDate Picker(以下、デートピッカー)やPicker View(以下、ピッカービュー)の使い方について説明してきた。
デートピッカーにはカウントダウンの時間を設定するためのモードがあるが、時分までの設定で、秒を設定することができない。秒を含めて設定をしたい人もいると思うので、本記事ではピッカービューを使ってカウントダウンの時分秒を設定するピッカーを作ることにする。
なお、以降の手順は前回記事の続きからなので、実装を試してみる人はそちらを先に読んでおくことをお勧めする。⇒「前回記事」
部品を配置する
デバイス画面にボタンを配置する(下図赤矢印)。黄緑枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Titleに「カウントダウン開始」、Text Colorを白、Backgroundに青を設定する。
次に、紫枠のアシスタントエディタボタンを押してViewController.swiftを開く。Ctrlを押しながらボタンをドラッグ&ドロップでソースコードに運んで吹き出しの設定画面を表示する(水色矢印)。
Connectionに「Action」、Nameに「startContDown」、Typeに「UIButton」、Eventに「Touch Up Inside」を設定し、Connectボタンを押す。これでボタンを押したイベントをコードで受けれるようになった。
次に、Ctrlキーを押しながらピッカービューをドラッグ&ドロップでソースコードまで運んで吹き出しの設定画面を表示させる。Connectionに「Outlet」、Nameに「testPickerView」を入力し、Connectボタンを押す。これで、ソースコードからピッカービューを操作できるようになった。
ついでにピッカービューの領域を把握しやすくするために背景色を変えておこう。黄緑枠のアトリビュートインスペクタボタンを押して設定画面を表示し、Backgroundをオレンジ色に設定する。
コンポーネントのサイズを指定する。
ホイールの間に「時間、分、秒」のラベルを表示して、何を指定するホイールなのかを分かりやすくしようと思うが、そのままでは下図のように真ん中のゼロを中心に数字が均等に並ぶためバランスが悪い。
そこで、ホイールのサイズを指定してバランスを整えることにする。サイズを指定するには以下のメソッドを用いる。
コンポーネントごとに下のメソッドが呼ばれるので、コンポーネントごとのホイールの幅を返す。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//サイズを返すメソッド func pickerView(pickerView: UIPickerView, widthForComponent component:Int) -> CGFloat { //サンプル switch component { case 0: return 100 case 1: return 50 default: return 30 } } |
上記コードのように幅を100、50、30にした場合、下図のように配置される。具体的には、100ピクセル、50ピクセル、30ピクセルのコンポーネントが5ピクセルの隙間を開けながら並び、その塊がピッカービューの左右端から同じ距離になるように配置される。なお、赤青緑の色は分りやすいように色付けしただけである。
コンポーネントの幅と隙間の合計がピッカービューの幅を超える場合は、ピッカービューの左端から配置されて右側のコンポーネントが見切れることになる。
下図は、ピッカービューの幅288に対して、コンポーネントの幅を150、100、100に指定した結果。
上記を考慮して、今回の検証では全てのコンポーネントの幅をピッカービューの幅の4分の1にし、文字列を左揃えにする。そして、ラベル「時間」はピッカービュー幅の4分の1のX座標、「分」はピッカービュー幅の2分の1のX座標、「秒」はピッカービュー幅の4分の3のX座標に配置する。
ViewController.swiftを開き、以下のコードのように変更する。
カウントダウンの作りはデートビューの記事で作ったものとほぼ同じで、ボタンが押されたらピッカービューの設定値を「残り秒数」としてクラス変数に保持し、1秒周期で残り秒数を減らしながらラベルに表示する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
// // ViewController.swift // import UIKit class ViewController: UIViewController,UIPickerViewDelegate,UIPickerViewDataSource { @IBOutlet weak var testPickerView: UIPickerView! @IBOutlet weak var testLabel: UILabel! var timer:NSTimer = NSTimer() var count:Int = 0 //時分秒のデータ let dataList = [[Int](0...24), [Int](0...60), [Int](0...60)] //最初からあるメソッド override func viewDidLoad() { super.viewDidLoad() //「時間」のラベルを追加 let hStr = UILabel() hStr.text = "時間" hStr.sizeToFit() hStr.frame = CGRectMake(testPickerView.bounds.width/4 - hStr.bounds.width/2, testPickerView.bounds.height/2 - (hStr.bounds.height/2), hStr.bounds.width, hStr.bounds.height) testPickerView.addSubview(hStr) //「分」のラベルを追加 let mStr = UILabel() mStr.text = "分" mStr.sizeToFit() mStr.frame = CGRectMake(testPickerView.bounds.width/2 - mStr.bounds.width/2, testPickerView.bounds.height/2 - (mStr.bounds.height/2), mStr.bounds.width, mStr.bounds.height) testPickerView.addSubview(mStr) //「秒」のラベルを追加 let sStr = UILabel() sStr.text = "秒" sStr.sizeToFit() sStr.frame = CGRectMake(testPickerView.bounds.width*3/4 - sStr.bounds.width/2, testPickerView.bounds.height/2 - (sStr.bounds.height/2), sStr.bounds.width, sStr.bounds.height) testPickerView.addSubview(sStr) } //コンポーネントの個数を返すメソッド func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { return dataList.count } //コンポーネントに含まれるデータの個数を返すメソッド func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return dataList[component].count } //サイズを返すメソッド func pickerView(pickerView: UIPickerView, widthForComponent component:Int) -> CGFloat { return testPickerView.bounds.width * 1/4 } //データを返すメソッド func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView { let pickerLabel = UILabel() pickerLabel.textAlignment = NSTextAlignment.Left pickerLabel.text = String(dataList[component][row]) pickerLabel.backgroundColor = UIColor.redColor() return pickerLabel } //ボタン押下時の呼び出しメソッド @IBAction func startCountDown(sender: UIButton) { //すでに動いているタイマーは停止する timer.invalidate() //カウントダウンする秒数を取得する。 count = dataList[0][testPickerView.selectedRowInComponent(0)] * 60 * 60 + dataList[0][testPickerView.selectedRowInComponent(1)] * 60 + dataList[0][testPickerView.selectedRowInComponent(2)] //1秒周期でcountDownメソッドを呼び出すタイマーを開始する。 timer = NSTimer.scheduledTimerWithTimeInterval(1, target:self, selector:"countDown", userInfo:nil, repeats:true) } //タイマーから呼び出されるメソッド func countDown(){ //カウントを減らす。 count-- //カウントダウン状況をラベルに表示 if(count > 0) { testLabel.text = "残り\(count)秒です。" } else { testLabel.text = "カウントダウン終了" timer.invalidate() } } } |
以下は実際のプレイ動画