この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
JGActionSheetは、豊富な機能を備えた、近代的なアクションシートです。
JGActionSheetは、UIActionSheetのすべての機能を持っていますが、それ以上に下記の機能を有しています。
- 複数のセクション
- ボタンやラベルのフルカスタマイズ
- ボタン以外のカスタムビュー
- ブロックのコールバック
- UIScrollViewによる、無制限のコンテンツ
JGActionSheetは、MITライセンスで公開されており、CocoaPodで簡単にインストールが可能です。
pod 'JGActionSheet'
なお、2016年3月現在、最新は、1.0.5です。
ライブラリの導入後は、下記のインポートで利用可能になります。
#import "JGActionSheet.h"
2 使用方法
(1) 簡単なサンプル
簡単なサンプルが、GitHubのREADME.mdに紹介されています。
使い方としては、まず、シートとして、JGActionSheetSectionオブジェクトを作成し、それをパラメータにして、JGActionSheetを生成します。
シートは、配列で渡されるため、複数のシートが作成可能であり、サンプルでは、2つのシートが渡されています。
また、ボタンを押した際のイベント処理は、setButtonPressedBlock:で非同期で処理され、どのシートの何番目のボタンを押されたかをNSIndexPathで受け取り、処理を記述することができます。
- (IBAction)tapActionSheet:(id)sender {
JGActionSheetSection *section1 = [JGActionSheetSection sectionWithTitle:@"Title" message:@"Message" buttonTitles:@[@"Yes", @"No"] buttonStyle:JGActionSheetButtonStyleDefault];
JGActionSheetSection *cancelSection = [JGActionSheetSection sectionWithTitle:nil message:nil buttonTitles:@[@"Cancel"] buttonStyle:JGActionSheetButtonStyleCancel];
NSArray *sections = @[section1, cancelSection];
JGActionSheet *sheet = [JGActionSheet actionSheetWithSections:sections];
[sheet setButtonPressedBlock:^(JGActionSheet *sheet, NSIndexPath *indexPath) {
[sheet dismissAnimated:YES];
}];
[sheet showInView:self.view animated:YES];
}
なお、ボタン選択時のブロックにdismissAnimated:がありますが、これが無いと、選択してもアクションシートは閉じません。
[sheet setButtonPressedBlock:^(JGActionSheet *sheet, NSIndexPath *indexPath) {
[sheet dismissAnimated:YES];
}];
(2) デリゲート(JGActionSheetDelegate)
先ほどの例では、ボタンを押した時のイベントをブロックで処理していましたが、これをデリゲートで受け取ることもできます。
JGActionSheet.hには、次のようなデリゲートが設定されています。
// アクションシートが表示される前
- (void)actionSheetWillPresent:(JGActionSheet *)actionSheet;
// アクションシートが表示された後
- (void)actionSheetDidPresent:(JGActionSheet *)actionSheet;
// アクションシートが非表示になる前
- (void)actionSheetWillDismiss:(JGActionSheet *)actionSheet;
// アクションシートが非表示になった後
- (void)actionSheetDidDismiss:(JGActionSheet *)actionSheet;
// アクションシートが選択された時
- (void)actionSheet:(JGActionSheet *)actionSheet pressedButtonAtIndexPath:(NSIndexPath *)indexPath;
先のサンプルをデリゲートで処理してみると、次のようになります。
@interface ViewController ()<JGActionSheetDelegate>
@end
@implementation ViewController
JGActionSheet *sheet = nil;
- (IBAction)tapActionSheet:(id)sender {
if (sheet == nil){
JGActionSheetSection *section1 = [JGActionSheetSection sectionWithTitle:@"Title" message:@"Message" buttonTitles:@[@"Yes", @"No"] buttonStyle:JGActionSheetButtonStyleDefault];
JGActionSheetSection *cancelSection = [JGActionSheetSection sectionWithTitle:nil message:nil buttonTitles:@[@"Cancel"] buttonStyle:JGActionSheetButtonStyleCancel];
NSArray *sections = @[section1, cancelSection];
sheet = [JGActionSheet actionSheetWithSections:sections];
[sheet setButtonPressedBlock:^(JGActionSheet *sheet, NSIndexPath *indexPath) {
[sheet dismissAnimated:YES];
NSLog(@"ButtonPressBlock section=%ld row=%ld",indexPath.section,indexPath.row);
}];
sheet.delegate = self;
}
[sheet showInView:self.view animated:YES];
}
- (void)actionSheetWillPresent:(JGActionSheet *)actionSheet{
NSLog(@"WillPresent:");
}
- (void)actionSheetDidPresent:(JGActionSheet *)actionSheet{
NSLog(@"DidPresent:");
}
-(void)actionSheetWillDismiss:(JGActionSheet *)actionSheet{
NSLog(@"WillDismiss:");
}
- (void)actionSheetDidDismiss:(JGActionSheet *)actionSheet{
NSLog(@"DidDismiss:");
}
-(void)actionSheet:(JGActionSheet *)actionSheet pressedButtonAtIndexPath:(NSIndexPath *)indexPath{
NSLog(@"pressedButtonAtIndexPath section=%ld row=%ld",indexPath.section,indexPath.row);
}
// 省略
動作している様子です。 ブロックでもデリゲートでも、同じようにNSIndexPathで選択されたボタンを取得できます。
画像をクリックすると動作を確認できます。
(3) ボタン
ボタンには、スタイルを指定することができます。
方法としては、シートに対して、setButtonStyle:メソッドで指定します。
JGActionSheetSection *section1 = [JGActionSheetSection sectionWithTitle:@"Title" message:@"Message" buttonTitles:@[@"Yes", @"No"] buttonStyle:JGActionSheetButtonStyleDefault];
[section1 setButtonStyle:JGActionSheetButtonStyleRed forButtonAtIndex:0];
[section1 setButtonStyle:JGActionSheetButtonStyleGreen forButtonAtIndex:1];
指定できるスタイルは、次の通りです。
- JGActionSheetButtonStyleDefault // 白地 細字
- JGActionSheetButtonStyleCancel // 白地 太字
- JGActionSheetButtonStyleRed // 赤地 細字
- JGActionSheetButtonStyleGreen // 緑地 細字
- JGActionSheetButtonStyleBlue // 青地 細字
(4) マージン
insetsでマージンを設定できます。
sheet.insets = UIEdgeInsetsMake(20.0f, 40.0f, 100.0f, 0.0f);
上の設定で、表示は次のようになります。
(5) ボタン以外のコントロール
ボタン以外のコントロールも配置することができます。
次の例は、UISliderを配置しているものです。
UISlider *c = [[UISlider alloc] init];
c.frame = (CGRect){CGPointZero, {290.0f, c.frame.size.height}};
JGActionSheetSection *section1 = [JGActionSheetSection sectionWithTitle:@"Content View Section" message:nil contentView:c];
JGActionSheetSection *section2 = [JGActionSheetSection sectionWithTitle:nil message:nil buttonTitles:@[@"OK",@"Cancel"] buttonStyle:JGActionSheetButtonStyleDefault];
NSArray *sections = @[section1, section2];
sheet = [JGActionSheet actionSheetWithSections:sections];
[sheet setButtonPressedBlock:^(JGActionSheet *sheet, NSIndexPath *indexPath) {
[sheet dismissAnimated:YES];
// 最初のセクションを取得する
JGActionSheet *s = [sheet.sections objectAtIndex:0];
// セクションのサブビューからUISliderを検索する
for(int i=0;i<3;i++){
UISlider *slider = [s.subviews objectAtIndex:i];
if([slider isMemberOfClass:[UISlider class]]){
NSLog(@"Slider Value = %f",slider.value);
break;
}
}
}];
sheet.delegate = self;
}
[sheet showInView:self.view animated:YES];
そして、実行している様子です。
画像をクリックすると動作を確認することができます。
配置したコントロールの値を読み取るには、グローバルで宣言されていない場合は、上のように芋づる式に検索するしかないでしょう。
作成したコントロールは、セクションのサブビューに格納されていますが、上の例では、これを順に検索しています。
サブビューに配置される順番は、タイトルがnilでない場合、0番目に入り、メッセージがnilでない場合その次の入り、コントロールはその次です。
従って、「タイトルあり(0番目)」、「メッセージ無(配置無し)」と決まっている場合は、その次の1番目に配置されるている事が確約されますので、決め打ちしても大丈夫です。
3 最後に
今回は、高機能なアクションシートである、JGActionSheetを紹介しました。 スクロールすることで、コンテンツが無制限に設定できたり、ボタン以外のコントロールが置けたりと、工夫すると面白い使い方ができるかも知れません。
4 参考資料
https://github.com/JonasGessner/JGActionSheet
http://cocoadocs.org/docsets/JGActionSheet/
Cocoapods Document