iPhone/iPad のアプリでポップアップして情報を表示する小さいウィンドウ(トースト)を表示する
Android の Toast のようなものは Apple からは提供されてないけど、UIButton でわりと簡単に代用できる。方法としては、UIButton をひとつ作ってアプリの window の subview として登録してやればいい。そして、ボタンを押したときに自身を removeFromSuperView してやれば画面から消える。以下、UITableViewController での実装例をメモ的にはってみる。
IB は使わず、ARC は有効にしてある。Empty アプリケーションを作り、Toast.m という UITableViewComtroller のサブクラスをひとつ作っている。ToastView とか独立したクラス化することも容易だけど、複数の Toast を表示させるときに多少制御する必要があって、少々面倒なのでここではやってない。
下のほうに表示されている黒っぽいウィンドウがそれ。
AppDelegate.m
Toast クラスのインスタンスをひとつ作り、rootViewController に登録しているだけ。
#import "Toast.h" - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; Table *table = [[Table alloc] initWithStyle:UITableViewStylePlain ]; [self.window setRootViewController:table]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; }
Toast.h
#import <UIKit/UIKit.h> @interface Table : UITableViewController { UIButton *toast; } @end
Toast.m
表示されたトーストは、フェード効果つきで表示され、クリックするとフェードアウトして消えるようにしてみた。Toast を複数表示しようとすると、前のものを消してから表示しなおすようにしてある。表示位置は、コメントアウトされているものを使いわけることで変更できる。なお、変更したメソッドのみ。文字列から Toast のサイズを決めるコードは、下記のコードをかなり使っている。
メソッドは書きかえが必要なところだけ。
#import "Toast.h" #import <QuartzCore/QuartzCore.h> // ウィンドウの角を丸めるためには QuartzCore.h の import が必要 // ちなみに角を丸める処理は結構重い - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 20; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } cell.textLabel.text = [NSString stringWithFormat:@"%d", indexPath.row ]; return cell; } - (void)show:(NSString*)text { if ( toast != nil ){ [toast removeFromSuperview]; } UIWindow *window = self.view.window; // テキストとフォントのサイズから、ラベルのサイズを決めてラベルに文字を書きこむ。 // 長いテキストは折りかえす。サイズは 280x60 で、これを越える場合は文末が省略される。 UIFont *font = [UIFont systemFontOfSize:16]; CGSize textSize = [text sizeWithFont:font constrainedToSize:CGSizeMake(280, 60)]; UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, textSize.width + 5, textSize.height + 5)]; label.backgroundColor = [UIColor clearColor]; label.textColor = [UIColor whiteColor]; label.font = font; label.text = text; label.numberOfLines = 0; label.shadowColor = [UIColor darkGrayColor]; // テキストの表示位置のオフセット label.shadowOffset = CGSizeMake(1, 1); // toast として使うボタンの生成 UIButton *v = [UIButton buttonWithType:UIButtonTypeCustom]; v.frame = CGRectMake(0, 0, textSize.width + 10, textSize.height + 10); label.center = CGPointMake(v.frame.size.width / 2, v.frame.size.height / 2); // label をボタンに登録する [v addSubview:label]; v.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7]; // 角を丸める処理 v.layer.cornerRadius = 5; CGPoint point = CGPointMake(window.frame.size.width/2, window.frame.size.height/2); // 上部に表示させる場合 //point = CGPointMake(window.frame.size.width / 2, 45); point = CGPointMake(window.frame.size.width / 2, window.frame.size.height - 45); // 中央に表示させる場合 // point = CGPointMake(window.frame.size.width/2, window.frame.size.height/2); point = CGPointMake(point.x, point.y); v.center = point; // ボタンを押したときに非表示にする [v addTarget:self action:@selector(hide:) forControlEvents: UIControlEventTouchDown]; // ボタンが表示されるときにフェード効果を付ける toast = v; toast.alpha = 0.0; [window addSubview: toast]; // toast.alpha を 0 から 1.0 まで 0.5 秒で変化させるアニメーションを登録する [UIView beginAnimations:nil context: NULL]; toast.alpha = 1.0f; [UIView setAnimationDuration:0.5]; // アニメーションを実行する。 [UIView commitAnimations]; } -(void)removeToast { // 画面から強制的に消す [toast removeFromSuperview]; // NSLog(@"remove"); } -(void)hide:(UIButton*)button { // toast.alpha を 1.0 から 0 まで 0.5 秒で変化させるアニメーションを登録する [UIView beginAnimations:nil context: NULL]; button.alpha = 0.0; [UIView setAnimationDuration:0.5]; [UIView setAnimationDelegate:self]; // アニメーション終了後に removeToast を呼びだす。 [UIView setAnimationDidStopSelector:@selector(removeToast)]; [UIView commitAnimations]; // NSLog(@"push"); } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // Toast を表示させる処理 [self show: [NSString stringWithFormat:@" 選ばれた項目は %d 番目っすよ", indexPath.row]]; } @end