UIPickerView をキーボードのように表示・非表示させる
環境:iOS Deployment Target 7.1
やりたいこと:
ボタンタップ時にキーボードが下からシュッと出てくるようにピッカーを表示させたい。
完了ボタンのタップで決定、ピッカー以外の部分をタップした時にはピッカーを隠す。
こんなかんじ。
やってること
ピッカー呼び出しボタンタップ時
- キャンセル用のビューを画面全体に被せる。ターゲット/アクションデザインパターンを使ってターゲットとアクションを設定している
- 画面外に作成していたピッカーと完了ボタンをアニメーションで画面内に移動させ表示
を行う。
完了ボタンのタップで選択中ピッカーを取得してピッカーを隠す。
ピッカー外のキャンセルビューをタップでピッカーを隠す。
サンプルコード
OverlayView.h
#import <UIKit/UIKit.h> @interface OverlayView : UIView @property(nonatomic, weak) id target; @property(nonatomic, assign) SEL action; @end
OverlayView.m
#import "OverlayView.h" @implementation OverlayView - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.target performSelector:self.action withObject:self afterDelay:0.0f]; } @end
PickerViewController.h
#import <UIKit/UIKit.h> @interface PickerViewController : UIViewController @end
PickerViewController.m
#import "PickerViewController.h" #import "OverlayView.h" @interface PickerViewController () < UIPickerViewDelegate, UIPickerViewDataSource > @property(nonatomic, strong) UIView *areaView; @property(nonatomic, strong) UIPickerView *areaPickerView; @property(nonatomic, strong) OverlayView *overlayView; @property(nonatomic, strong) NSArray *areaList; @property(nonatomic, strong) UILabel *areaLabel; @end @implementation PickerViewController - (void)viewDidLoad { [super viewDidLoad]; self.areaList = @[ @[@"1", @"北海道"], @[@"2", @"東北"], @[@"3", @"関東・信越"], @[@"4", @"東海・北陸・近畿"], @[@"5", @"中国・四国"], @[@"6", @"九州"], @[@"7", @"沖縄"], ]; // ピッカー呼び出しボタン作成 UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 50)]; button.center = CGPointMake(self.view.bounds.size.width / 2, 100); button.backgroundColor = [UIColor greenColor]; [button setTitle:@"エリア選択" forState:UIControlStateNormal]; [button addTarget:self action:@selector(showAreaView:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; // エリア表示用ラベルの作成 self.areaLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 150, 50)]; self.areaLabel.center = CGPointMake(self.view.bounds.size.width / 2, 150); self.areaLabel.textAlignment = NSTextAlignmentCenter; [self.view addSubview:self.areaLabel]; // キャンセル用ビューの作成 self.overlayView = [[OverlayView alloc] initWithFrame:CGRectZero]; self.overlayView.target = self; self.overlayView.action = @selector(hideAreaView); self.overlayView.backgroundColor = [UIColor blackColor]; self.overlayView.alpha = 0.4; [self.view addSubview:self.overlayView]; // エリア選択ピッカーの作成 [self buildAreaPickerView]; } - (void)showAreaView:(UIButton*)button { [self.view bringSubviewToFront:_overlayView]; // 最前面に移動 [self.view bringSubviewToFront:_areaView]; // 最前面に移動 self.overlayView.frame = [[UIScreen mainScreen] bounds]; [UIView animateWithDuration:.20 animations:^{ self.areaView.transform = CGAffineTransformMakeTranslation(0, -(AREA_PICKER_ACCESSORY_HEIGHT + AREA_PICKER_HEIGHT)); }]; } - (void)hideAreaView { [UIView animateWithDuration:.20 animations:^{ self.areaView.transform = CGAffineTransformIdentity; }]; self.overlayView.frame = CGRectZero; } static const float AREA_PICKER_ACCESSORY_HEIGHT = 44; static const float AREA_PICKER_HEIGHT = 216; - (void)buildAreaPickerView { float height = self.view.bounds.size.height; float width = self.view.bounds.size.width; // 1. アクセサリビューとピッカービューを乗せるビューの作成 float areaViewHeight = AREA_PICKER_ACCESSORY_HEIGHT + AREA_PICKER_HEIGHT; self.areaView = [[UIView alloc] initWithFrame:CGRectMake(0, height, width, areaViewHeight)]; [self.view addSubview:self.areaView]; // 2-1. アクセサリビュー作成 UIView *areaPickerAccessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, AREA_PICKER_ACCESSORY_HEIGHT)]; areaPickerAccessoryView.backgroundColor = [UIColor greenColor]; // 2-2. 決定ボタン作成 const float DONE_BUTTON_WEDTH = 80; UIButton *doneBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; doneBtn.frame = CGRectMake(width - DONE_BUTTON_WEDTH, 4, DONE_BUTTON_WEDTH, 36); doneBtn.backgroundColor = [UIColor whiteColor]; [doneBtn setTitle:@"完了" forState:UIControlStateNormal]; [doneBtn addTarget:self action:@selector(performAreaDoneButtonAction) forControlEvents:UIControlEventTouchUpInside]; [areaPickerAccessoryView addSubview:doneBtn]; [self.areaView addSubview:areaPickerAccessoryView]; // 3. ピッカー作成 self.areaPickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, AREA_PICKER_ACCESSORY_HEIGHT, width, AREA_PICKER_HEIGHT)]; self.areaPickerView.backgroundColor = [UIColor whiteColor]; self.areaPickerView.delegate = self; self.areaPickerView.dataSource = self; [self.areaPickerView selectRow:2 inComponent:0 animated:NO]; // 初期値設定 [self.areaView addSubview:self.areaPickerView]; } - (void)performAreaDoneButtonAction { NSInteger row = [self.areaPickerView selectedRowInComponent:0]; NSLog(@"areaCode:%@, areaName:%@", self.areaList[row][0], self.areaList[row][1]); self.areaLabel.text = self.areaList[row][1]; [self hideAreaView]; } // UIPickerViewDataSource, UIPickerViewDelegate delegate - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 1; } - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { return self.areaList.count; } - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { return self.areaList[row][1]; } @end
※追記
もっと簡単なやり方を書いた。
UITextField の inputView に UIPickerView を設定する