iPhoneでの日付の入力方法は、ドラムロールのようなこちら
「UIDatePicker」で行うのが普通だと思います。
これが入力ように画面を覆うように表示されていたらすごく邪魔ですよね?
なので、こいつを文字列入力のキーボードのように下からニョキっと出るように改造してみたいと思います。
動作イメージ
1.nibファイルの作成
まず完成図はこちら、
UIを設置する
- Viewを配置「幅:320 × 高さ:480」で設置する
- UIDatePickerを最下部に設置する
- UIToolBarをUIDatePickerの上に設置する
- UIBarButtonItemを2つUIToolBarに設置する
- ボタンの間に「Flexible Space Bar Button Item」を設置する
UIの設定を変更する
- File’s Ownerの設定
- 「Custom Class」に「ModalDatePicker」と入力する(この後に作るViewControllerの名前を設定)
- Viewの設定
- 「Background」をDefaultの色なしに設定する
- 「Width」を320 「Height」を480で設定する
- 「File’s Owner」とReferencing Outletsで接続する
- DatePickerの設定
- 「File’s Owner」とReferencing Outletsで接続する(この後に作成するViewControllerのhファイルに設定が必要)
- 左ボタンの設定
- 「File’s Owner」とSent Actionsで接続する(この後に作成するViewControllerのhファイルに設定が必要)
- 右ボタンの設定
- 「File’s Owner」とSent Actionsで接続する(この後に作成するViewControllerのhファイルに設定が必要)
2.ViewControllerの作成
- 「ModalViewContoller.h」の編集
#import <UIKit/UIKit.h>
@class ModalDatePicker;
@protocol ModalDatePickerDelegate
- (void) didDatePickerOKClicked:(ModalDatePicker *) controller selectedDate:(NSDate *) selectedDate pickerName:(NSString *) pickerName pickerTag:(NSInteger) pickerTag;
- (void) didDatePickerCancelClicked:(ModalDatePicker *) controller pickerName:(NSString *) pickerName pickerTag:(NSInteger) pickerTag;
@end
@interface ModalDatePicker : UIViewController
@property (weak, nonatomic) IBOutlet UIDatePicker *picker;
@property (nonatomic, assign) id<ModalDatePickerDelegate> delegate;
@property (nonatomic, retain) NSString *pickerName;
@property (nonatomic, assign) NSInteger pickerTag;
@property (nonatomic, retain) NSDate *dispDate;
- (IBAction)okClicked:(id)sender;
- (IBAction)cancelClicked:(id)sender;
@end
- 「ModalViewController.m」の編集
#import "ModalDatePicker.h"
@interface ModalDatePicker ()
@end
@implementation ModalDatePicker
@synthesize picker = _picker, delegate = _delegate, pickerName = _pickerName, dispDate = _dispDate, pickerTag = _pickerTag;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)viewDidAppear:(BOOL)animated {
if (self.dispDate != nil) {
[self.picker setDate:self.dispDate];
}
}
- (void)viewDidUnload
{
[self setPicker: nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (IBAction)okClicked:(id)sender {
[self.delegate didDatePickerOKClicked:self selectedDate:self.picker.date pickerName:self.pickerName pickerTag:self.pickerTag];
}
- (IBAction)cancelClicked:(id)sender {
[self.delegate didDatePickerCancelClicked:self pickerName:self.pickerName pickerTag:self.pickerTag];
}
@end
これで「ModalDatePicker」は作成完了です。
使用方法
- ボタンを押下したら、「ModalDatePicker」を表示する
- (IBAction)showBtnClicked:(id)sender
{
// self.pickarは、ModalDatePicker型のインスタンス変数です。
self.picker = [[ModalDatePicker alloc] init];
self.datePicker.pickerName = @"どこから呼ばれたか特定する為に設定";
self.datePicker.dispDate = (self.dispDate != nil) ? self.dispDate : [NSDate date];
self.datePicker.delegate = self;
[self showModel:self.datePicker.view];
}
- (void) showModel:(UIView *) modalView
{
UIWindow *mainWindow = (((AppDelegate *) [UIApplication sharedApplication].delegate).window);
CGPoint middleCenter = modalView.center;
CGSize offSize = [UIScreen mainScreen].bounds.size;
CGPoint offScreenCenter = CGPointMake(offSize.width / 2.0, offSize.height * 1.5);
modalView.center = offScreenCenter;
[mainWindow addSubview:modalView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
modalView.center = middleCenter;
[UIView commitAnimations];
}
- 「ModalDataPicker」のdelegateを実装する
- (void) didDatePickerOKClicked:(ModalDatePicker *)controller selectedDate:(NSDate *)selectedDate pickerName:(NSString *)pickerName pickerTag:(NSInteger) pickerTag
{
[self hideModal:controller.view];
controller.delegate = nil;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy年MM月dd日"];
if ([pickerName isEqualToString:@"どこから呼ばれたか特定する為に設定") {
self.date = selectedDate;
self.label.text = [formatter stringFromDate:self.date];
}
}
- (void) didDatePickerCancelClicked:(ModalDatePicker *)controller pickerName:(NSString *)pickerName pickerTag:(NSInteger) pickerTag
{
[self hideModal:controller.view];
controller.delegate = nil;
}
- (void) hideModal:(UIView*) modalView
{
CGSize offSize = [UIScreen mainScreen].bounds.size;
CGPoint offScreenCenter = CGPointMake(offSize.width / 2.0, offSize.height * 1.5);
[UIView beginAnimations:nil context:(__bridge_retained void *)modalView];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(hideModalEnded:finished:context:)];
modalView.center = offScreenCenter;
[UIView commitAnimations];
}
- (void) hideModalEnded:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
UIView *modalView = (__bridge_transfer UIView *)context;
[modalView removeFromSuperview];
}
これで「ModalDatePicker」の呼び出しと、delegateの実装ができました。
1つのViewContllerで複数の「ModalDatePicker」を呼び出す必要がある場合は、
を使用してどのボタンから呼び出されたかを判断することができます。
これを、応用することで様々な入力方法をモーダルウインドウ化出来るようになります。