├── screen3.png
├── actionsheet.gif
├── screenshot.png
├── screenshot2.gif
├── STModalDemo
├── STModalDemo
│ ├── lufei@2x.jpg
│ ├── onepiece@2x.jpeg
│ ├── share_friend@2x.png
│ ├── share_wechat@2x.png
│ ├── AlertViewController.h
│ ├── ActionSheetViewController.h
│ ├── ViewController.h
│ ├── AppDelegate.h
│ ├── main.m
│ ├── Images.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Info.plist
│ ├── AppDelegate.m
│ ├── AlertViewController.m
│ ├── Base.lproj
│ │ ├── LaunchScreen.xib
│ │ └── Main.storyboard
│ ├── ActionSheetViewController.m
│ └── ViewController.m
├── STModalDemo.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── project.pbxproj
├── STModal
│ ├── STFrontModal
│ │ ├── STFrontModal.h
│ │ └── STFrontModal.m
│ ├── STModalUtil.h
│ ├── STAlertView
│ │ ├── STAlertView.h
│ │ └── STAlertView.m
│ ├── STModal.h
│ ├── STActionSheet
│ │ ├── STActionSheet.h
│ │ └── STActionSheet.m
│ └── STModal.m
└── STModalDemoTests
│ ├── Info.plist
│ └── STModalDemoTests.m
├── .gitignore
├── README.md
└── LICENSE
/screen3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhenlintie/STModalDemo/HEAD/screen3.png
--------------------------------------------------------------------------------
/actionsheet.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhenlintie/STModalDemo/HEAD/actionsheet.gif
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhenlintie/STModalDemo/HEAD/screenshot.png
--------------------------------------------------------------------------------
/screenshot2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhenlintie/STModalDemo/HEAD/screenshot2.gif
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/lufei@2x.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhenlintie/STModalDemo/HEAD/STModalDemo/STModalDemo/lufei@2x.jpg
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/onepiece@2x.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhenlintie/STModalDemo/HEAD/STModalDemo/STModalDemo/onepiece@2x.jpeg
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/share_friend@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhenlintie/STModalDemo/HEAD/STModalDemo/STModalDemo/share_friend@2x.png
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/share_wechat@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhenlintie/STModalDemo/HEAD/STModalDemo/STModalDemo/share_wechat@2x.png
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/AlertViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // AlertViewController.h
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/5.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AlertViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/ActionSheetViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ActionSheetViewController.h
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/7.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ActionSheetViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/5.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "STModal.h"
11 |
12 | @interface ViewController : UIViewController
13 |
14 |
15 | @end
16 |
17 |
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/5.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/STModalDemo/STModal/STFrontModal/STFrontModal.h:
--------------------------------------------------------------------------------
1 | //
2 | // STFrontModal.h
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/8/14.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import "STModal.h"
10 |
11 | @interface STFrontModal : NSObject
12 |
13 | + (void)showView:(UIView *)view animated:(BOOL)animated;
14 | + (void)hide:(BOOL)animated;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/5.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | # We recommend against adding the Pods directory to your .gitignore. However
23 | # you should judge for yourself, the pros and cons are mentioned at:
24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
25 | #
26 | #Pods/
27 |
--------------------------------------------------------------------------------
/STModalDemo/STModal/STModalUtil.h:
--------------------------------------------------------------------------------
1 | //
2 | // Header.h
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/7.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 |
10 | #define STModalRGBA(r,g,b,a) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a]
11 |
12 | static inline UIImage *st_imageWithColor(UIColor *color){
13 | UIGraphicsBeginImageContext(CGSizeMake(1, 1));
14 | CGContextRef context = UIGraphicsGetCurrentContext();
15 | CGContextSetFillColorWithColor(context, color.CGColor);
16 | CGContextFillRect(context, CGRectMake(0, 0, 1, 1));
17 | UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
18 | UIGraphicsEndImageContext();
19 | return img;
20 | }
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/STModalDemo/STModalDemoTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.steven.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 自定义弹出视图
2 |
3 | ## STModal介绍
4 | ### 特点
5 |
6 | 1. 只需关心需要弹出的视图
7 | 2. 可自定义动画
8 | 3. 当弹出多个视图时,以栈的方式显示
9 |
10 | ### 更新
11 | 2015-08-14 优化了显示方式,增加了一个显示方式STFrontModal
12 |
13 | ### 用法
14 |
15 | ```
16 | UIView *contentView = [UIView new];
17 | ...
18 |
19 | STModal *modal = [STModal modalWithContentView:contentView];
20 | [modal show:YES];
21 |
22 | //或者
23 | STModal *modal = [STModal modal];
24 | [modal showContentView:contentView animated:YES];
25 |
26 | ```
27 | ### 截图
28 |
29 | 
30 |
31 | ## STAlertView
32 |
33 | * 基于`STModal`做的一个提示视图。
34 | * 效果图
35 |
36 | 
37 |
38 | ## STActionSheet
39 | * 基于`STModal`做的一个选择视图。
40 | * 效果图
41 |
42 | 
43 |
44 | ## STFrontModal
45 | 
--------------------------------------------------------------------------------
/STModalDemo/STModalDemoTests/STModalDemoTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // STModalDemoTests.m
3 | // STModalDemoTests
4 | //
5 | // Created by zhenlintie on 15/6/5.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface STModalDemoTests : XCTestCase
13 |
14 | @end
15 |
16 | @implementation STModalDemoTests
17 |
18 | - (void)setUp {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown {
24 | // Put teardown code here. This method is called after the invocation of each test method in the class.
25 | [super tearDown];
26 | }
27 |
28 | - (void)testExample {
29 | // This is an example of a functional test case.
30 | XCTAssert(YES, @"Pass");
31 | }
32 |
33 | - (void)testPerformanceExample {
34 | // This is an example of a performance test case.
35 | [self measureBlock:^{
36 | // Put the code you want to measure the time of here.
37 | }];
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 sTeven
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.steven.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/STModalDemo/STModal/STAlertView/STAlertView.h:
--------------------------------------------------------------------------------
1 | //
2 | // STAlertView.h
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/5.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface STAlertView : UIView
12 |
13 | /**
14 | * 初始化一个视图
15 | */
16 | - (instancetype)initWithTitle:(NSString *)title
17 | image:(UIImage *)image
18 | message:(NSString *)message
19 | buttonTitles:(NSArray *)buttonTitles;
20 |
21 | /**
22 | * 显示/隐藏
23 | */
24 | - (void)show:(BOOL)animated;
25 | - (void)hide:(BOOL)animated;
26 |
27 | /**
28 | * 事件回调
29 | */
30 | @property (strong, nonatomic) void (^actionHandler)(NSInteger index);
31 | /**
32 | * 显示隐藏后回调
33 | */
34 | @property (strong, nonatomic) void (^didShowHandler)();
35 | @property (strong, nonatomic) void (^didHideHandler)();
36 |
37 | @property (copy, nonatomic, readonly) NSString *title;
38 | @property (copy, nonatomic, readonly) NSString *message;
39 | @property (copy, nonatomic, readonly) UIImage *image;
40 | @property (copy, nonatomic, readonly) NSArray *buttonTitles;
41 |
42 | @property (assign, nonatomic, readonly) BOOL onShow;
43 |
44 | // 点击外部,是否隐藏,默认NO
45 | @property (assign, nonatomic) BOOL hideWhenTapOutside;
46 |
47 | @end
48 |
49 | @interface STAlertView (Show)
50 |
51 | + (instancetype)showTitle:(NSString *)title
52 | image:(UIImage *)image
53 | message:(NSString *)message
54 | buttonTitles:(NSArray *)buttonTitles
55 | handler:(void(^)(NSInteger index))handler;
56 |
57 | + (instancetype)showTitle:(NSString *)title message:(NSString *)message hideDelay:(CGFloat)delay;
58 | + (instancetype)showTitle:(NSString *)title message:(NSString *)message;
59 |
60 | @end
61 |
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/5.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 | - (void)applicationWillResignActive:(UIApplication *)application {
24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
26 | }
27 |
28 | - (void)applicationDidEnterBackground:(UIApplication *)application {
29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
31 | }
32 |
33 | - (void)applicationWillEnterForeground:(UIApplication *)application {
34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
35 | }
36 |
37 | - (void)applicationDidBecomeActive:(UIApplication *)application {
38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39 | }
40 |
41 | - (void)applicationWillTerminate:(UIApplication *)application {
42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/AlertViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // AlertViewController.m
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/5.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import "AlertViewController.h"
10 | #import "STAlertView.h"
11 |
12 | @interface AlertViewController ()
13 |
14 | @end
15 |
16 | @implementation AlertViewController
17 |
18 | - (void)viewDidLoad {
19 | [super viewDidLoad];
20 | // Do any additional setup after loading the view.
21 | }
22 |
23 | - (IBAction)tip:(id)sender {
24 | NSArray *buttons = nil;
25 | // buttons = @[@"查看更多",@"稍后提醒",@"不看了"];
26 | STAlertView *alert = [[STAlertView alloc] initWithTitle:@"海贼王"
27 | image:[UIImage imageNamed:@"onepiece.jpeg"]
28 | message:@"传奇海贼哥尔·D·罗杰在临死前曾留下关于其毕生的财富“One Piece”的消息,由此引得群雄并起,众海盗们为了这笔传说中的巨额财富展开争夺,各种势力、政权不断交替,整个世界进入了动荡混乱的“大海贼时代”。\n生长在东海某小村庄的路飞受到海贼香克斯的精神指引,决定成为一名出色的海盗。为了达成这个目标,并找到万众瞩目的One Piece,路飞踏上艰苦的旅程。一路上他遇到了无数磨难,也结识了索隆、娜美、乌索普、香吉、罗宾等一众性格各异的好友。他们携手一同展开充满传奇色彩的大冒险。"
29 | buttonTitles:buttons];
30 |
31 | alert.hideWhenTapOutside = YES;
32 | [alert setDidShowHandler:^{
33 | NSLog(@"显示了");
34 | }];
35 | [alert setDidHideHandler:^{
36 | NSLog(@"消失了");
37 | }];
38 | [alert setActionHandler:^(NSInteger index) {
39 | switch (index) {
40 | case 0:
41 | {
42 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://baike.baidu.com/link?url=puPuzaUO9pAbfCUuJygbsxhrO6ZCXaUeatthEUEcJHRkGskVaciOLfQ1JK_PTtIiZntrID_VtO5TQxtsd1TnrEUJF1UoPGTjXjGk4-swLnWE1GN2J6n0TS81-7bKdQiFpRX1FihvRNcDOCifv7WnldMKoX9MbtmbCvLUw4_ui-BCURimyIOuMXToghtTwA2P"]];
43 | break;
44 | }
45 | default:
46 | break;
47 | }
48 | }];
49 | [alert show:YES];
50 | }
51 |
52 | - (IBAction)notif:(id)sender {
53 | NSString *title = @"通知";
54 | NSString *message = @"您的手机已经欠费了,速交!";
55 | //// [STAlertView showTitle:nil message:message];
56 | //// [STAlertView showTitle:title message:message hideDelay:2];
57 | //// [STAlertView showTitle:title message:nil];
58 | [STAlertView showTitle:title
59 | image:nil
60 | message:message
61 | buttonTitles:@[@"这就去",@"就不交"]
62 | handler:^(NSInteger index) {
63 |
64 | }];
65 |
66 | }
67 |
68 | @end
69 |
--------------------------------------------------------------------------------
/STModalDemo/STModal/STModal.h:
--------------------------------------------------------------------------------
1 | //
2 | // STModal.h
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/5.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | * @discussion 主视图显示位置
13 | */
14 | typedef NS_ENUM(NSUInteger, STModelPositionMode) {
15 | STModelPositionCenter,
16 | STModelPositionCenterTop,
17 | STModelPositionCenterBottom,
18 | STModelPositionCustom
19 | };
20 |
21 | /**
22 | * @discussion 执行的动画块
23 | * @return 动画所需时间
24 | */
25 | typedef CGFloat (^st_modal_animation)();
26 |
27 | /**
28 | * @discussion 回调
29 | */
30 | typedef void (^st_modal_block)();
31 |
32 | /**
33 | * @discussion 弹出视图控制器
34 | */
35 | @interface STModal : NSObject
36 |
37 | + (instancetype)modal;
38 | + (instancetype)modalWithContentView:(UIView *)contentView;
39 |
40 | /**
41 | * @discussion 所显示的主视图
42 | */
43 | @property (strong, nonatomic, readonly) UIView *contentView;
44 |
45 | /**
46 | * @discussion contentView位置,默认STModelPositionCenter
47 | */
48 | @property (assign, nonatomic) STModelPositionMode positionMode;
49 |
50 | /**
51 | * @discussion 自定义位置,只有当position为STModelPositionCustom时生效
52 | */
53 | @property (assign, nonatomic) CGPoint position;
54 |
55 | /**
56 | * @discussion 点击contentView外的区域是否执行hide,默认为NO
57 | */
58 | @property (assign, nonatomic) BOOL hideWhenTouchOutside;
59 |
60 | /**
61 | * @discussion 当touchOutDismiss为YES时,是否发生动画,默认是YES
62 | */
63 | @property (assign, nonatomic) BOOL animatedHideWhenTouchOutside;
64 |
65 | /**
66 | * @discussion 背景是否加蒙版,默认为YES
67 | */
68 | @property (assign, nonatomic) BOOL dimBackgroundWhenShow;
69 |
70 | /**
71 | * @discussion 自定义背景蒙版颜色,默认为nil
72 | */
73 | @property (strong, nonatomic) UIColor *dimBackgroundColor;
74 |
75 |
76 | //// 当不设置执行动画时,且animated为YES,会默认执行一个过渡动画
77 | /**
78 | * @discussion 显示时的动画
79 | */
80 | @property (strong, nonatomic) st_modal_animation showAnimation;
81 |
82 | /**
83 | * @discussion 隐藏时的动画
84 | */
85 | @property (strong, nonatomic) st_modal_animation hideAnimation;
86 |
87 | /**
88 | * @discussion 显示后/隐藏后回调
89 | */
90 | @property (strong, nonatomic) st_modal_block didShowHandler;
91 | @property (strong, nonatomic) st_modal_block didHideHandler;
92 |
93 | /**
94 | * @discussion 显示
95 | */
96 | - (void)show:(BOOL)animated;
97 |
98 | /**
99 | * @discussion 显示指定的contentView,若之前已设置,则替换掉。
100 | */
101 | - (void)showContentView:(UIView *)contentView animated:(BOOL)animated;
102 |
103 | /**
104 | * @discussion 是否已经显示
105 | */
106 | @property (assign, readonly, nonatomic) BOOL onShow;
107 |
108 | /**
109 | * @discussion 隐藏
110 | */
111 | - (void)hide:(BOOL)animated;
112 |
113 | @end
114 |
--------------------------------------------------------------------------------
/STModalDemo/STModal/STFrontModal/STFrontModal.m:
--------------------------------------------------------------------------------
1 | //
2 | // STFrontModal.m
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/8/14.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import "STFrontModal.h"
10 |
11 | @interface STModal (STFrontModal)
12 |
13 | @property (strong, nonatomic) UIView *containerView;
14 |
15 | @end
16 |
17 | @interface STFrontModal ()
18 |
19 | @property (strong, nonatomic) STModal *modal;
20 |
21 | @end
22 |
23 | @implementation STFrontModal
24 |
25 | + (instancetype)sharedFrontModal{
26 | static STFrontModal *_shared = nil;
27 | static dispatch_once_t onceToken;
28 | dispatch_once(&onceToken, ^{
29 | _shared = [[STFrontModal alloc] _init];
30 | });
31 | return _shared;
32 | }
33 |
34 | - (instancetype)_init{
35 | if (self = [super init]){
36 | _modal = [STModal new];
37 | _modal.hideWhenTouchOutside = YES;
38 | _modal.positionMode = STModelPositionCenterBottom;
39 | _modal.showAnimation = [self showAnimation];
40 | _modal.hideAnimation = [self hideAnimation];
41 | }
42 | return self;
43 | }
44 |
45 | - (instancetype)init{
46 | return [[self class] sharedFrontModal];
47 | }
48 |
49 | + (void)showView:(UIView *)view animated:(BOOL)animated{
50 | [[self sharedFrontModal] showView:view animated:animated];
51 | }
52 |
53 | + (void)hide:(BOOL)animated{
54 | [[self sharedFrontModal] hide:animated];
55 | }
56 |
57 | - (void)showView:(UIView *)view animated:(BOOL)animated{
58 | [_modal showContentView:view animated:animated];
59 | }
60 |
61 | - (void)hide:(BOOL)animated{
62 | [_modal hide:animated];
63 | }
64 |
65 | - (st_modal_animation)showAnimation{
66 | return ^CGFloat(){
67 | _modal.contentView.transform = CGAffineTransformMakeTranslation(0.0f, CGRectGetHeight(_modal.contentView.frame));
68 |
69 | CGFloat d = 0.35;
70 | [UIView animateWithDuration:d
71 | delay:0
72 | usingSpringWithDamping:1
73 | initialSpringVelocity:0
74 | options:UIViewAnimationOptionCurveEaseOut
75 | animations:^{
76 | _modal.contentView.transform = CGAffineTransformIdentity;
77 | [self keyWindow].transform = CGAffineTransformMakeScale(0.85, 0.85);
78 | }
79 | completion:nil];
80 | return d;
81 | };
82 | }
83 |
84 | - (st_modal_animation)hideAnimation{
85 | return ^CGFloat(){
86 | CGFloat d = 0.3;
87 | [UIView animateWithDuration:d
88 | delay:0
89 | usingSpringWithDamping:1
90 | initialSpringVelocity:0
91 | options:UIViewAnimationOptionCurveEaseInOut
92 | animations:^{
93 | _modal.contentView.transform = CGAffineTransformMakeTranslation(0.0f, CGRectGetHeight(_modal.contentView.frame)+5);
94 | [self keyWindow].transform = CGAffineTransformIdentity;
95 | }
96 | completion:nil];
97 | return d;
98 | };
99 | }
100 |
101 | - (UIWindow *)keyWindow{
102 | return [UIApplication sharedApplication].keyWindow;
103 | }
104 |
105 | @end
106 |
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/ActionSheetViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ActionSheetViewController.m
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/7.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import "ActionSheetViewController.h"
10 | #import "STActionSheet.h"
11 |
12 | @interface ActionSheetViewController ()
13 |
14 | @end
15 |
16 | @implementation ActionSheetViewController
17 |
18 | - (void)viewDidLoad {
19 | [super viewDidLoad];
20 |
21 | }
22 |
23 | - (IBAction)wxShare:(id)sender {
24 | NSArray *items = @[[STActionItem itemWithTitle:@"好友" icon:[UIImage imageNamed:@"share_friend"]],
25 | [STActionItem itemWithTitle:@"朋友圈" icon:[UIImage imageNamed:@"share_wechat"]]];
26 | STActionSheet *actionSheet = [[STActionSheet alloc] initWithTitle:@"分享到微信"
27 | cancelItem:[STActionItem itemWithTitle:@"取消"]
28 | items:items];
29 | [actionSheet show:YES];
30 | }
31 | - (IBAction)deleteClicked:(id)sender {
32 |
33 | [STActionSheet showTitle:@"确定删除?\n删除后将无法恢复数据"
34 | items:@[[STActionItem desdructiveItem:@"删除"]]
35 | cancel:[STActionItem itemWithTitle:@"取消"]
36 | actionHandler:^(STActionItem *item, NSInteger index) {
37 | NSLog(@"删除了...");
38 | }
39 | cancelHandler:^(STActionItem *cancelItem) {
40 | NSLog(@"取消了");
41 | }];
42 | }
43 | - (IBAction)persons:(id)sender {
44 | NSDictionary *att = @{NSFontAttributeName:[UIFont boldSystemFontOfSize:16],
45 | NSForegroundColorAttributeName:[UIColor colorWithRed:0.8 green:0.8 blue:0.95 alpha:0.9]};
46 | STActionSheet *actionSheet = [[STActionSheet alloc] initWithTitle:@"传奇海贼哥尔·D·罗杰在临死前曾留下关于其毕生的财富“One Piece”的消息,由此引得群雄并起,众海盗们为了这笔传说中的巨额财富展开争夺,各种势力、政权不断交替,整个世界进入了动荡混乱的“大海贼时代”。\n生长在东海某小村庄的路飞受到海贼香克斯的精神指引,决定成为一名出色的海盗。为了达成这个目标,并找到万众瞩目的One Piece,路飞踏上艰苦的旅程。一路上他遇到了无数磨难,也结识了索隆、娜美、乌索普、香吉、罗宾等一众性格各异的好友。他们携手一同展开充满传奇色彩的大冒险。\n\n主要人物:"
47 | cancelTitle:nil
48 | otherButtonTitles:@[@"蒙奇•D•路飞",
49 | @"罗罗诺亚•索隆",
50 | @"娜美",
51 | @"乌索普",
52 | @"山治",
53 | @"托尼托尼•乔巴",
54 | @"妮可·罗宾",
55 | @"弗兰奇",
56 | @"布鲁克",
57 | @"哥尔·D·罗杰",
58 | @"西尔巴兹·雷利",
59 | @"爱德华·纽盖特(白胡子)",
60 | @"香克斯(红发)",
61 | @"马歇尔·D·蒂奇(黑胡子)",
62 | @"乔拉可尔·米霍克(鹰眼)"]
63 | attribute:att];
64 | actionSheet.hideWhenTouchOutside = YES;
65 | [actionSheet show:YES];
66 | }
67 |
68 | - (IBAction)createBuilding:(id)sender {
69 | [STActionSheet showTitle:nil
70 | otherButtonTitles:@[@"楼主",@"1楼",@"2楼",@"3楼",@"4楼",@"5楼",@"6楼",@"7楼",]
71 | cancel:nil
72 | attribute:nil];
73 | }
74 |
75 | @end
76 |
--------------------------------------------------------------------------------
/STModalDemo/STModal/STActionSheet/STActionSheet.h:
--------------------------------------------------------------------------------
1 | //
2 | // STActionSheet.h
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/6.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class STActionItem;
12 | typedef void(^st_sheet_action_handler)(STActionItem *item, NSInteger index);
13 |
14 | @interface STActionSheet : UIView
15 |
16 | /**
17 | * `cancelTitle`与`otherButtonTitles`的属性,当`attribute`存在,则用`attribute`
18 | * 否则用默认的
19 | */
20 | - (instancetype)initWithTitle:(NSString *)title
21 | cancelTitle:(NSString *)cancelTitle
22 | otherButtonTitles:(NSArray *)otherButtonTitles
23 | attribute:(NSDictionary *)attribute;
24 |
25 | // 此初始化忽略`itemAttribute`
26 | - (instancetype)initWithTitle:(NSString *)title cancelItem:(STActionItem *)cancelItem items:(NSArray *)items;
27 |
28 | /**
29 | * 显示/隐藏
30 | */
31 | - (void)show:(BOOL)animated;
32 | - (void)hide:(BOOL)animated;
33 |
34 | /**
35 | * 点击外部是否隐藏,默认为YES
36 | */
37 | @property (nonatomic, assign) BOOL hideWhenTouchOutside;
38 |
39 | @property (nonatomic, readonly) NSString *title;
40 | @property (nonatomic, readonly) STActionItem *cancelItem;
41 | @property (nonatomic, readonly) NSArray *items;
42 |
43 | /**
44 | * 事件回调
45 | */
46 | @property (strong, nonatomic) st_sheet_action_handler actionHandler;
47 | @property (strong, nonatomic) void(^didCancelHandler)(STActionItem *cancelItem);
48 | @property (strong, nonatomic) void (^didShowHandler)();
49 | @property (strong, nonatomic) void (^didHideHandler)();
50 |
51 | @end
52 |
53 |
54 | @interface STActionSheet (Show)
55 |
56 | + (instancetype)showTitle:(NSString *)title
57 | items:(NSArray *)items
58 | cancel:(STActionItem *)cancelItem;
59 | + (instancetype)showItems:(NSArray *)items
60 | actionHandler:(st_sheet_action_handler)actionHandler;
61 | + (instancetype)showTitle:(NSString *)title
62 | items:(NSArray *)items
63 | actionHandler:(st_sheet_action_handler)actionHandler;
64 | + (instancetype)showTitle:(NSString *)title
65 | items:(NSArray *)items
66 | cancel:(STActionItem *)cancelItem
67 | actionHandler:(st_sheet_action_handler)actionHandler
68 | cancelHandler:(void(^)(STActionItem *cancelItem))canceledHandler;
69 |
70 | + (instancetype)showTitle:(NSString *)title
71 | otherButtonTitles:(NSArray *)otherButtonTitles
72 | cancel:(NSString *)cancelTitle
73 | attribute:(NSDictionary *)attribute;
74 | + (instancetype)showTitle:(NSString *)title
75 | otherButtonTitles:(NSArray *)otherButtonTitles
76 | cancel:(NSString *)cancelTitle
77 | attribute:(NSDictionary *)attribute
78 | actionHandler:(st_sheet_action_handler)actionHandler
79 | cancelHandler:(void(^)(STActionItem *cancelItem))canceledHandler;
80 |
81 | @end
82 |
83 |
84 | /**
85 | * STActionSheet的元素
86 | */
87 | @interface STActionItem : NSObject
88 |
89 | /**
90 | * 快速生成
91 | */
92 | + (instancetype)itemWithTitle:(NSString *)title;
93 | + (instancetype)itemWithAttributedTitle:(NSAttributedString *)attributedTitle;
94 | + (instancetype)itemWithTitle:(NSString *)title icon:(UIImage *)icon;
95 | + (instancetype)itemWithAttributedTitle:(NSAttributedString *)attributedTitle icon:(UIImage *)icon;
96 | + (instancetype)itemWithTitle:(NSString *)title attribute:(NSDictionary *)attribute;
97 |
98 | /**
99 | * 初始化
100 | */
101 | - (instancetype)initWithTitle:(NSString *)title icon:(UIImage *)icon;
102 | - (instancetype)initWithAttributedTitle:(NSAttributedString *)attributedTitle icon:(UIImage *)icon;
103 |
104 | @property (copy, nonatomic, readonly) NSString *title;
105 | @property (copy, nonatomic, readonly) UIImage *icon;
106 |
107 | @property (copy, nonatomic, readonly) NSAttributedString *attributedTitle;
108 |
109 | @end
110 |
111 | @interface STActionItem (Common)
112 |
113 | /**
114 | * 提醒格式的item
115 | */
116 | + (instancetype)desdructiveItem:(NSString *)title;
117 | + (instancetype)desdructiveItem:(NSString *)title icon:(UIImage *)icon;
118 |
119 | @end
120 |
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/5.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "STModalUtil.h"
11 | #import "STFrontModal.h"
12 |
13 | @interface ViewController ()
14 |
16 |
17 | @property (strong, nonatomic) UILabel *aboutLabel;
18 |
19 | @end
20 |
21 | @implementation ViewController{
22 | STModal *_aboutModal;
23 | STModal *_storyModal;
24 | STModal *_customModal;
25 | UITableView *_settingTableView;
26 | }
27 |
28 | - (void)viewDidLoad {
29 | [super viewDidLoad];
30 | [self test1];
31 | }
32 |
33 | - (void)test1{
34 | [self addButton:120 tag:0 title:@"关于"];
35 | [self addButton:180 tag:1 title:@"故事"];
36 | [self addButton:260 tag:2 title:@"随机位置"];
37 | [self addButton:320 tag:3 title:@"设置"];
38 | }
39 |
40 | - (void)addButton:(CGFloat)top tag:(NSInteger)tag title:(NSString *)title{
41 | UIButton *tap = [UIButton buttonWithType:UIButtonTypeSystem];
42 | tap.frame = CGRectMake(120, top, 80, 45);
43 | tap.titleLabel.font = [UIFont boldSystemFontOfSize:20];
44 | [tap setTitle:title forState:UIControlStateNormal];
45 | tap.tag = tag;
46 | tap.backgroundColor = [UIColor lightGrayColor];
47 | [tap addTarget:self action:@selector(tapped:) forControlEvents:UIControlEventTouchUpInside];
48 | [self.view addSubview:tap];
49 | }
50 |
51 | - (void)tapped:(UIButton *)button{
52 | switch (button.tag) {
53 | case 0:{
54 | [self showAboutModal];
55 | break;
56 | }
57 | case 1:{
58 | [self showStoryModal];
59 | break;
60 | }
61 | case 2:{
62 | [self showCustomModal];
63 | break;
64 | }
65 | case 3:{
66 | [self showSetting];
67 | break;
68 | }
69 | default:
70 | break;
71 | }
72 | }
73 |
74 | - (void)showAboutModal{
75 | if (!_aboutModal){
76 | _aboutModal = [self createModal:nil];
77 | }
78 | if (!_aboutLabel){
79 | _aboutLabel = [self createLabel];
80 | _aboutLabel.userInteractionEnabled = YES;
81 | // _aboutLabel.backgroundColor = [UIColor blackColor];
82 | _aboutLabel.text = @"这是一个自定义的小标签\n\n\n";
83 | UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 20, 80, 40)];
84 | btn.backgroundColor = [UIColor colorWithRed:0.5 green:0.3 blue:0.3 alpha:0.3];
85 | [btn setTitle:@"看故事" forState:UIControlStateNormal];
86 | [btn addTarget:self action:@selector(showStoryModal) forControlEvents:UIControlEventTouchUpInside];
87 | [_aboutLabel addSubview:btn];
88 | [_aboutLabel sizeToFit];
89 | }
90 | [_aboutModal showContentView:_aboutLabel animated:YES];
91 | }
92 |
93 | - (void)showStoryModal{
94 | if (!_storyModal){
95 | UILabel *label = [self createLabel];
96 | label.backgroundColor = [UIColor colorWithRed:0.3 green:0.1 blue:0.5 alpha:.1];
97 | label.textColor = [UIColor colorWithWhite:0 alpha:1];
98 | label.text = @"老师把小明叫到了教室外。\n老师:“你的作业做的越来越差了,这是怎么回事?”\n小明:“老师,等我找找原因,下午告诉你好吗?”\n老师:“好吧!”\n下午,老师又把小明叫到了教室外。\n老师:“找到原因了吗?”\n小明:“找到了,我爷爷说作业越来越难,他也没办法。”\n老师:“滚出去!”\n\n\n";
99 | CGSize s = [label sizeThatFits:CGSizeMake(300, 1000)];
100 | label.frame = CGRectMake(0, 0, s.width, s.height);
101 | label.userInteractionEnabled = YES;
102 |
103 | UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, s.height-40, 190, 40)];
104 | [btn setBackgroundImage:st_imageWithColor([UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1]) forState:UIControlStateNormal];
105 | [btn setTitle:@"显示自定义" forState:UIControlStateNormal];
106 | [btn addTarget:self action:@selector(showCustomModal) forControlEvents:UIControlEventTouchUpInside];
107 | [label addSubview:btn];
108 |
109 | _storyModal = [self createModal:label];
110 | _storyModal.dimBackgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:0.2];
111 | }
112 | [_storyModal show:YES];
113 | }
114 |
115 | - (void)showCustomModal{
116 | if (!_customModal){
117 | UILabel *customLabel = [self createLabel];
118 | customLabel.text = @"*****************\n自定义的位置\n*****************";
119 | customLabel.textColor = [UIColor blackColor];
120 | [customLabel sizeToFit];
121 | _customModal = [STModal modalWithContentView:customLabel];
122 | _customModal.positionMode = STModelPositionCustom;
123 | _customModal.dimBackgroundColor = [[UIColor purpleColor] colorWithAlphaComponent:.1];
124 | _customModal.hideWhenTouchOutside = YES;
125 | }
126 | _customModal.position = CGPointMake(110+random()%100, 300+random()%200);
127 | [_customModal show:YES];
128 | }
129 |
130 | - (void)showSetting{
131 | if (!_settingTableView){
132 | _settingTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 300) style:UITableViewStylePlain];
133 | _settingTableView.delegate = self;
134 | _settingTableView.dataSource = self;
135 | [_settingTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
136 | _settingTableView.backgroundColor = [UIColor whiteColor];
137 | _settingTableView.rowHeight = 44;
138 |
139 | UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 300-40, 190, 40)];
140 | [btn setBackgroundImage:st_imageWithColor([UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1]) forState:UIControlStateNormal];
141 | [btn setTitle:@"显示自定义" forState:UIControlStateNormal];
142 | [btn addTarget:self action:@selector(showCustomModal) forControlEvents:UIControlEventTouchUpInside];
143 | [_settingTableView addSubview:btn];
144 | }
145 | [STFrontModal showView:_settingTableView animated:YES];
146 | }
147 |
148 | - (UILabel *)createLabel{
149 | UILabel *label = [UILabel new];
150 | label.numberOfLines = 0;
151 | label.textAlignment = NSTextAlignmentLeft;
152 | label.textColor = [UIColor colorWithWhite:1 alpha:0.85];
153 | return label;
154 | }
155 |
156 | - (STModal *)createModal:(UIView *)contentView{
157 | STModal *modal = [STModal modalWithContentView:contentView];
158 | modal.hideWhenTouchOutside = YES;
159 | return modal;
160 | }
161 |
162 | #pragma mark - tableview delegate / datasource
163 |
164 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
165 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
166 | cell.textLabel.text = @"点击设置";
167 | cell.accessoryType = random()%4+1;
168 | return cell;
169 | }
170 |
171 | - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index{
172 | return 1;
173 | }
174 |
175 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
176 | return 10;
177 | }
178 |
179 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
180 | [STFrontModal hide:YES];
181 | }
182 |
183 | @end
184 |
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
30 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
71 |
81 |
91 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
--------------------------------------------------------------------------------
/STModalDemo/STModal/STModal.m:
--------------------------------------------------------------------------------
1 | //
2 | // STModal.m
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/5.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import "STModal.h"
10 |
11 | /**
12 | * @discussion 公共窗口类
13 | */
14 | @interface STModalWindow : NSObject
15 |
16 | + (instancetype)sharedModalWindow;
17 |
18 | - (void)showModal:(STModal *)modal animated:(BOOL)animated duration:(CGFloat)duration completion:(void(^)())comletion;
19 |
20 | - (void)hideModal:(STModal *)modal animated:(BOOL)animated duration:(CGFloat)duration completion:(void(^)())comletion;
21 |
22 | @end
23 |
24 |
25 | @interface STModal ()
26 |
27 | @property (strong, nonatomic) UIView *containerView;
28 |
29 | @property (strong, nonatomic) UIView *backgroundTapView;
30 |
31 | @property (strong, nonatomic) UITapGestureRecognizer *tap;
32 |
33 | @property (assign, nonatomic) BOOL onShowing;
34 |
35 | @property (assign, nonatomic) BOOL onTop;
36 |
37 | @end
38 |
39 | @implementation STModal
40 |
41 | + (instancetype)modal{
42 | return [self new];
43 | }
44 |
45 | + (instancetype)modalWithContentView:(UIView *)contentView{
46 | STModal *modal = [self modal];
47 | [modal addModalContentView:contentView];
48 | return modal;;
49 | }
50 |
51 | - (instancetype)init{
52 | if (self = [super init]){
53 | _positionMode = STModelPositionCenter;
54 | _position = CGPointMake(CGRectGetWidth([UIScreen mainScreen].bounds)/2.0, CGRectGetHeight([UIScreen mainScreen].bounds)/2.0);
55 | _onShowing = NO;
56 | _onTop = NO;
57 | _hideWhenTouchOutside = NO;
58 | _animatedHideWhenTouchOutside = YES;
59 | _dimBackgroundWhenShow = YES;
60 | }
61 | return self;
62 | }
63 |
64 | - (void)addModalContentView:(UIView *)contentView{
65 | _contentView = contentView;
66 | }
67 |
68 | #pragma mark - setter / getter
69 |
70 | - (void)setPositionMode:(STModelPositionMode)positionMode{
71 | if (_positionMode != positionMode){
72 | _positionMode = positionMode;
73 | [self updateContentViewPosition];
74 | }
75 | }
76 |
77 | - (UIView *)containerView{
78 | if (!_containerView){
79 | CGSize size = [UIScreen mainScreen].bounds.size;
80 | _containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
81 | _containerView.backgroundColor = [UIColor clearColor];
82 |
83 | _backgroundTapView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
84 | _backgroundTapView.backgroundColor = [UIColor clearColor];
85 | [_containerView addSubview:_backgroundTapView];
86 |
87 | _tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped)];
88 | _tap.enabled = _hideWhenTouchOutside;
89 | [_backgroundTapView addGestureRecognizer:_tap];
90 | }
91 | return _containerView;
92 | }
93 |
94 | - (st_modal_animation)showAnimation{
95 | if (!_showAnimation){
96 | return ^CGFloat(){
97 | CGFloat d = 0.3;
98 | _containerView.alpha = 0;
99 | [UIView animateWithDuration:d
100 | animations:^{
101 | _containerView.alpha = 1;
102 | }];
103 | return d;
104 | };
105 | }
106 | return _showAnimation;
107 | }
108 |
109 | - (st_modal_animation)hideAnimation{
110 | if (!_hideAnimation){
111 | return ^CGFloat(){
112 | CGFloat d = 0.3;
113 | [UIView animateWithDuration:d
114 | animations:^{
115 | _containerView.alpha = 0;
116 | }];
117 | return d;
118 | };
119 | }
120 | return _hideAnimation;
121 | }
122 |
123 | - (BOOL)onShow{
124 | return _onShowing;
125 | }
126 |
127 | - (STModalWindow *)window{
128 | return [STModalWindow sharedModalWindow];
129 | }
130 |
131 | #pragma mark - action
132 |
133 | - (void)setHideWhenTouchOutside:(BOOL)hideWhenTouchOutside{
134 | _hideWhenTouchOutside = hideWhenTouchOutside;
135 | _tap.enabled = _hideWhenTouchOutside;
136 | }
137 |
138 | - (void)tapped{
139 | if (_hideWhenTouchOutside && !CGRectContainsPoint(_contentView.frame, [_tap locationInView:_containerView])){
140 | [self hide:_animatedHideWhenTouchOutside];
141 | }
142 | }
143 |
144 | #pragma mark - for show / hide
145 |
146 | - (void)updateContentViewPosition{
147 | switch (_positionMode) {
148 | case STModelPositionCenter:{
149 | _contentView.center = CGPointMake(CGRectGetMidX(_containerView.bounds), CGRectGetMidY(_containerView.bounds));
150 | break;
151 | }
152 | case STModelPositionCenterTop:{
153 | _contentView.center = CGPointMake(CGRectGetMidX(_containerView.bounds), CGRectGetHeight(_contentView.bounds)/2.0);
154 | break;
155 | }
156 | case STModelPositionCenterBottom:{
157 | _contentView.center = CGPointMake(CGRectGetMidX(_containerView.bounds), CGRectGetHeight(_containerView.bounds)-CGRectGetHeight(_contentView.bounds)/2.0);
158 | break;
159 | }
160 | case STModelPositionCustom:{
161 | _contentView.center = self.position;
162 | }
163 | default:
164 | break;
165 | }
166 | }
167 |
168 | - (void)prepareUIForShow{
169 | [self.containerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
170 | [_containerView addSubview:_backgroundTapView];
171 | [self.containerView addSubview:_contentView];
172 | [self updateContentViewPosition];
173 | }
174 |
175 | - (void)showContentView:(UIView *)contentView animated:(BOOL)animated{
176 | NSAssert(contentView!=nil, @"没有可显示的视图");
177 | [self addModalContentView:contentView];
178 | [self show:animated];
179 | }
180 |
181 | - (void)show:(BOOL)animated{
182 | NSAssert(_contentView!=nil, @"没有可显示的视图");
183 | [self prepareUIForShow];
184 | [self.window showModal:self animated:animated duration:animated?self.showAnimation():0 completion:self.didShowHandler];
185 | }
186 |
187 | - (void)hide:(BOOL)animated{
188 | [self.window hideModal:self animated:animated duration:animated?self.hideAnimation():0 completion:self.didHideHandler];
189 | }
190 |
191 | @end
192 |
193 |
194 | #define STModalWindowDefaultBackgroundColor [UIColor colorWithWhite:0 alpha:0.55]
195 |
196 | @interface STModalWindow ()
197 |
198 | @property (strong, nonatomic) NSMutableArray *modalsStack;
199 |
200 | @property (strong, nonatomic) UIWindow *window;
201 |
202 | @property (strong, nonatomic) UIView *dimBackgroundView;
203 |
204 | @property (assign, nonatomic) BOOL shouldDimBackground;
205 |
206 | @end
207 |
208 | @implementation STModalWindow{
209 | BOOL _onShowing;
210 | }
211 |
212 | + (instancetype)sharedModalWindow{
213 | static dispatch_once_t onceToken;
214 | static STModalWindow *_sharedModalWindow = nil;
215 | dispatch_once(&onceToken, ^{
216 | _sharedModalWindow = [[self alloc] init];
217 | });
218 | return _sharedModalWindow;
219 | }
220 |
221 | - (instancetype)init{
222 | if (self = [super init]){
223 | _modalsStack = [[NSMutableArray alloc] init];
224 | _window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
225 | _window.windowLevel = UIWindowLevelAlert;
226 | _window.backgroundColor = [UIColor clearColor];
227 | _window.opaque = NO;
228 | _dimBackgroundView = [[UIView alloc] initWithFrame:_window.bounds];
229 | [_window addSubview:_dimBackgroundView];
230 | }
231 | return self;
232 | }
233 |
234 | #pragma mark - public modal operation
235 |
236 | - (void)showModal:(STModal *)modal animated:(BOOL)animated duration:(CGFloat)duration completion:(void(^)())comletion{
237 | STModal *topModal = [self topModal];
238 | [self pushModal:modal];
239 | [self reloadData];
240 | _window.hidden = NO;
241 | [self transitionFromModal:topModal
242 | toModal:modal
243 | animated:animated
244 | duration:duration
245 | completion:comletion];
246 | }
247 |
248 | - (void)hideModal:(STModal *)modal animated:(BOOL)animated duration:(CGFloat)duration completion:(void(^)())comletion{
249 | if ([self hasModal:modal]){
250 | if ([[self topModal] isEqual:modal]){
251 | STModal *toModal = (_modalsStack.count>1)?_modalsStack[_modalsStack.count-2]:nil;
252 | [self transitionFromModal:modal
253 | toModal:toModal
254 | animated:animated
255 | duration:duration
256 | completion:^{
257 | [self popModal:modal];
258 | [modal.containerView removeFromSuperview];
259 |
260 | BOOL isNoModal = nil == [self topModal];
261 | if (isNoModal){
262 | _window.hidden = YES;
263 | }
264 | else{
265 | [self reloadData];
266 | }
267 | if (comletion){
268 | comletion();
269 | }
270 | }];
271 | }
272 | else{
273 | [self popModal:modal];
274 | [modal.containerView removeFromSuperview];
275 | }
276 | }
277 | }
278 |
279 | #pragma mark - show or hide
280 |
281 | - (void)transitionFromModal:(STModal *)fromModal
282 | toModal:(STModal *)toModal
283 | animated:(BOOL)animated
284 | duration:(CGFloat)duration
285 | completion:(void(^)())completion{
286 |
287 | CGFloat fromA = 0, toA = 0;
288 | UIColor *fromColor = nil, *toColor = nil;
289 |
290 | BOOL(^colosIsEqual)(UIColor *, UIColor *) = ^BOOL(UIColor *color1, UIColor *color2){
291 | if (color1 && color2){
292 | CGFloat r1, r2, g1, g2, b1, b2, a1, a2;
293 | [color1 getRed:&r1 green:&g1 blue:&b1 alpha:&a1];
294 | [color2 getRed:&r2 green:&g2 blue:&b2 alpha:&a2];
295 | return (r1==r2)&&(g1==g2)&&(b1==b2)&&(a1==a2);
296 | }
297 | else if (!color1 && !color2){
298 | return YES;
299 | }
300 | return NO;
301 | };
302 |
303 | if (nil != fromModal){
304 | fromA = fromModal.dimBackgroundWhenShow?1:0;
305 | fromColor = fromModal.dimBackgroundColor?:STModalWindowDefaultBackgroundColor;
306 | }
307 |
308 | if (nil != toModal){
309 | toA = toModal.dimBackgroundWhenShow?1:0;
310 | toColor = toModal.dimBackgroundColor?:STModalWindowDefaultBackgroundColor;
311 | }
312 |
313 | _dimBackgroundView.alpha = fromA;
314 | _dimBackgroundView.backgroundColor = fromColor;
315 | if (fromA == toA && colosIsEqual(fromColor, toColor)){
316 | // 如果没有任何变化UIView动画会立即结束,采用以下方法进行回调
317 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
318 | if (completion){
319 | completion();
320 | }
321 | });
322 | }
323 | else{
324 | [UIView animateWithDuration:animated?duration:0
325 | animations:^{
326 | _dimBackgroundView.alpha = toA;
327 | _dimBackgroundView.backgroundColor = toColor;
328 | }
329 | completion:^(BOOL finished) {
330 | if (completion){
331 | completion();
332 | }
333 | }];
334 | }
335 | }
336 |
337 | - (void)reloadData{
338 | STModal *topModal = [self topModal];
339 | if (topModal){
340 | self.shouldDimBackground = topModal.dimBackgroundWhenShow;
341 | _dimBackgroundView.backgroundColor = topModal.dimBackgroundColor?:STModalWindowDefaultBackgroundColor;
342 |
343 | [topModal.containerView removeFromSuperview];
344 | [_window addSubview:topModal.containerView];
345 |
346 | [[_modalsStack valueForKey:@"containerView"] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
347 | [(UIView *)obj setHidden:(obj!=topModal.containerView)];
348 | }];
349 | }
350 | }
351 |
352 | - (void)setShouldDimBackground:(BOOL)shouldDimBackground{
353 | _shouldDimBackground = shouldDimBackground;
354 | _dimBackgroundView.alpha = _shouldDimBackground?1:0;
355 | }
356 |
357 | #pragma mark - stack operation
358 |
359 | - (void)pushModal:(STModal *)modal{
360 | if ([self hasModal:modal]){
361 | [self popModal:modal];
362 | }
363 | [_modalsStack addObject:modal];
364 | }
365 |
366 | - (STModal *)popModal:(STModal *)modal{
367 | if ([self hasModal:modal]){
368 | [_modalsStack removeObject:modal];
369 | }
370 | return [self topModal];
371 | }
372 |
373 | - (STModal *)topModal{
374 | if (_modalsStack.count > 0){
375 | return [_modalsStack lastObject];
376 | }
377 | return nil;
378 | }
379 |
380 | - (BOOL)hasModal:(STModal *)modal{
381 | return (nil!=modal)&&([_modalsStack indexOfObject:modal] != NSNotFound);
382 | }
383 |
384 | @end
--------------------------------------------------------------------------------
/STModalDemo/STModal/STAlertView/STAlertView.m:
--------------------------------------------------------------------------------
1 | //
2 | // STAlertView.m
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/5.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import "STAlertView.h"
10 | #import "STModal.h"
11 | #import "STModalUtil.h"
12 |
13 | #define kSTAlertWidth 300
14 | #define kSTAlertPaddingV 11
15 | #define kSTAlertPaddingH 18
16 | #define kSTAlertRadius 13
17 | #define kSTAlertButtonHeight 40
18 |
19 | @interface STAlertView ()
20 |
21 | @property (strong, nonatomic) UIView *backgroundView;
22 | @property (strong, nonatomic) UIView *containerView;
23 | @property (strong, nonatomic) UIScrollView *scrollView;
24 | @property (strong, nonatomic) UILabel *titleLabel;
25 | @property (strong, nonatomic) UIImageView *imageView;
26 | @property (strong, nonatomic) UILabel *messageLabel;
27 | @property (strong, nonatomic) NSMutableArray *buttons;
28 | @property (strong, nonatomic) NSMutableArray *lines;
29 |
30 | @end
31 |
32 | @implementation STAlertView{
33 | STModal *_modal;
34 | BOOL _didLayouted;
35 |
36 | CGFloat _scrollBottom;
37 | CGFloat _buttonsHeight;
38 | CGFloat _maxContentWidth;
39 | CGFloat _maxAlertViewHeight;
40 | }
41 |
42 | - (instancetype)initWithTitle:(NSString *)title image:(UIImage *)image message:(NSString *)message buttonTitles:(NSArray *)buttonTitles{
43 | if (self = [self initWithFrame:CGRectZero]){
44 | _title = [title copy];
45 | _image = image;
46 | _message = [message copy];
47 | _buttonTitles = [NSArray arrayWithArray:buttonTitles];
48 | }
49 | return self;
50 | }
51 |
52 | - (instancetype)initWithFrame:(CGRect)frame{
53 | if (self = [super initWithFrame:CGRectMake(0, 0, kSTAlertWidth, 0)]){
54 | [self loadData];
55 | [self loadUI];
56 | }
57 | return self;
58 | }
59 |
60 | - (void)loadData{
61 | _didLayouted = NO;
62 | _hideWhenTapOutside = NO;
63 | _buttons = [NSMutableArray new];
64 | _lines = [NSMutableArray new];
65 |
66 | _modal = [STModal modalWithContentView:self];
67 | _modal.hideWhenTouchOutside = NO;
68 | _modal.dimBackgroundWhenShow = NO;
69 | _modal.showAnimation = [self showAnimation];
70 | _modal.hideAnimation = [self hideAnimation];
71 | }
72 |
73 | - (void)loadUI{
74 | _backgroundView = [UIView new];
75 | _backgroundView.backgroundColor = STModalRGBA(120, 125, 130, 1);
76 |
77 | _backgroundView.layer.cornerRadius = kSTAlertRadius;
78 | _backgroundView.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.5].CGColor;
79 | _backgroundView.layer.shadowOffset = CGSizeZero;
80 | _backgroundView.layer.shadowOpacity = 1;
81 | _backgroundView.layer.shadowRadius = kSTAlertRadius;
82 | _backgroundView.layer.borderWidth = 0.5;
83 | _backgroundView.layer.borderColor = STModalRGBA(110, 115, 120, 1).CGColor;
84 |
85 | _containerView = [UIView new];
86 | _containerView.layer.cornerRadius = kSTAlertRadius;
87 | _containerView.layer.masksToBounds = YES;
88 |
89 | _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
90 | [_containerView addSubview:_scrollView];
91 |
92 | [self addSubview:_backgroundView];
93 | [self addSubview:_containerView];
94 | }
95 |
96 | - (st_modal_animation)showAnimation{
97 | return ^CGFloat(){
98 | self.alpha = 0;
99 | CGFloat d1 = 0.2, d2 = 0.15;
100 | self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.4, 0.4);
101 | [UIView animateWithDuration:d1 animations:^{
102 | self.alpha = 1;
103 | self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.1, 1.1);
104 | } completion:^(BOOL finished) {
105 | [UIView animateWithDuration:d2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
106 | self.alpha = 1;
107 | self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 1);
108 | } completion:^(BOOL finished2) {
109 | }];
110 | }];
111 | return (d1+d2);
112 | };
113 | }
114 |
115 | - (st_modal_animation)hideAnimation{
116 | return ^CGFloat(){
117 | CGFloat d1 = 0.2, d2 = 0.1;
118 | [UIView animateWithDuration:d2 animations:^{
119 | self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.1, 1.1);
120 | } completion:^(BOOL finished){
121 | [UIView animateWithDuration:d1 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
122 | self.alpha = 0;
123 | self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.4, 0.4);
124 | } completion:^(BOOL finished2){
125 | }];
126 | }];
127 | return (d1+d2);
128 | };
129 | }
130 |
131 | #pragma mark - prepare for show
132 |
133 | - (void)prepareForShow{
134 | if (_didLayouted){
135 | return;
136 | }
137 | [self resetViews];
138 | _scrollBottom = 0;
139 | CGFloat insetY = kSTAlertPaddingV;
140 | _maxContentWidth = kSTAlertWidth-2*kSTAlertPaddingH;
141 | _maxAlertViewHeight = [UIScreen mainScreen].bounds.size.height-50;
142 | [self loadTitle];
143 | [self loadImage];
144 | [self loadMessage];
145 | _buttonsHeight = kSTAlertButtonHeight*((_buttonTitles.count>2||_buttonTitles.count==0)?_buttonTitles.count:1);
146 | self.frame = CGRectMake(0, 0, kSTAlertWidth, MIN(MAX(_scrollBottom+2*insetY+_buttonsHeight, 2*kSTAlertRadius+kSTAlertPaddingV), _maxAlertViewHeight));
147 | _backgroundView.frame = self.bounds;
148 | _backgroundView.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
149 | _containerView.frame = self.bounds;
150 | _scrollView.frame = CGRectMake(0, insetY, CGRectGetWidth(_containerView.frame),MIN(_scrollBottom, CGRectGetHeight(_containerView.frame)-2*insetY-_buttonsHeight));
151 | _scrollView.contentSize = CGSizeMake(_maxContentWidth, _scrollBottom);
152 | _didLayouted = YES;
153 |
154 | [self loadButtons];
155 | }
156 |
157 | - (void)resetViews{
158 | if (_titleLabel){
159 | [_titleLabel removeFromSuperview];
160 | _titleLabel.text = @"";
161 | }
162 | if (_imageView){
163 | [_imageView removeFromSuperview];
164 | _imageView.image = nil;
165 | }
166 | if (_messageLabel){
167 | [_messageLabel removeFromSuperview];
168 | _messageLabel.text = @"";
169 | }
170 | if (_buttons.count > 0){
171 | [_buttons makeObjectsPerformSelector:@selector(removeFromSuperview)];
172 | [_buttons removeAllObjects];
173 | }
174 | if (_lines.count > 0){
175 | [_lines makeObjectsPerformSelector:@selector(removeFromSuperview)];
176 | [_lines removeAllObjects];
177 | }
178 | }
179 |
180 | - (void)addLabel:(UILabel *)label maxHeight:(CGFloat)maxHeight{
181 | CGSize size = [label sizeThatFits:CGSizeMake(_maxContentWidth, maxHeight)];
182 | label.frame = CGRectMake(kSTAlertPaddingH, _scrollBottom, _maxContentWidth, size.height);
183 | [_scrollView addSubview:label];
184 |
185 | _scrollBottom = CGRectGetMaxY(label.frame)+kSTAlertPaddingV;
186 | }
187 |
188 | - (void)addLine:(CGRect)frame toView:(UIView *)view{
189 | UIView *line = [[UIView alloc] initWithFrame:frame];
190 | line.backgroundColor = STModalRGBA(160, 170, 160, 0.5);
191 | [view addSubview:line];
192 | [_lines addObject:line];
193 | }
194 |
195 | - (void)loadTitle{
196 | if (!_title){
197 | return;
198 | }
199 | if (!_titleLabel){
200 | _titleLabel = [UILabel new];
201 | _titleLabel.textColor = [UIColor colorWithWhite:1 alpha:0.85];
202 | _titleLabel.font = [UIFont systemFontOfSize:15];
203 | _titleLabel.textAlignment = NSTextAlignmentCenter;
204 | _titleLabel.numberOfLines = 0;
205 | }
206 | _titleLabel.text = _title;
207 | [self addLabel:_titleLabel maxHeight:100];
208 | [self addLine:CGRectMake(kSTAlertPaddingH, _scrollBottom, _maxContentWidth, 0.5) toView:_scrollView];
209 | _scrollBottom += kSTAlertPaddingV;
210 | }
211 |
212 | - (void)loadImage{
213 | if (!_image){
214 | return;
215 | }
216 | if (!_imageView){
217 | _imageView = [UIImageView new];
218 | }
219 | _imageView.image = _image;
220 | CGSize size = _image.size;
221 | if (size.width > _maxContentWidth){
222 | size = CGSizeMake(_maxContentWidth, size.height/size.width*_maxContentWidth);
223 | }
224 | _imageView.frame = CGRectMake(kSTAlertPaddingH+_maxContentWidth/2-size.width/2, _scrollBottom, size.width, size.height);
225 | [_scrollView addSubview:_imageView];
226 |
227 | _scrollBottom = CGRectGetMaxY(_imageView.frame)+kSTAlertPaddingV;
228 | }
229 |
230 | - (void)loadMessage{
231 | if (!_message){
232 | return;
233 | }
234 | if (!_messageLabel){
235 | _messageLabel = [UILabel new];
236 | _messageLabel.textColor = STModalRGBA(240, 245, 255, 1);
237 | _messageLabel.font = [UIFont systemFontOfSize:17];
238 | _messageLabel.textAlignment = NSTextAlignmentCenter;
239 | _messageLabel.numberOfLines = 0;
240 | }
241 | _messageLabel.text = _message;
242 | [self addLabel:_messageLabel maxHeight:100000];
243 | }
244 |
245 | - (void)loadButtons{
246 | if (!_buttonTitles || _buttonTitles.count==0){
247 | return;
248 | }
249 | CGFloat buttonHeight = kSTAlertButtonHeight;
250 | CGFloat buttonWidth = kSTAlertWidth;
251 | CGFloat top = CGRectGetHeight(_containerView.frame)-_buttonsHeight;
252 | [self addLine:CGRectMake(0, top-0.5, buttonWidth, 0.5) toView:_containerView];
253 | if (1 == _buttonTitles.count){
254 | [self addButton:CGRectMake(0, top, buttonWidth, buttonHeight) title:[_buttonTitles firstObject] tag:0];
255 | }
256 | else if (2 == _buttonTitles.count){
257 | [self addButton:CGRectMake(0, top, buttonWidth/2, buttonHeight) title:[_buttonTitles firstObject] tag:0];
258 | [self addButton:CGRectMake(0+buttonWidth/2, top, buttonWidth/2, buttonHeight) title:[_buttonTitles lastObject] tag:1];
259 | [self addLine:CGRectMake(0+buttonWidth/2-.5, top, 0.5, buttonHeight) toView:_containerView];
260 | }
261 | else{
262 |
263 | for (NSInteger i=0; i<_buttonTitles.count; i++){
264 | [self addButton:CGRectMake(0, top, buttonWidth, buttonHeight) title:_buttonTitles[i] tag:i];
265 | top += buttonHeight;
266 | if (_buttonTitles.count-1!=i){
267 | [self addLine:CGRectMake(0, top, buttonWidth, 0.5) toView:_containerView];
268 | }
269 | }
270 | [_lines enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
271 | [_containerView bringSubviewToFront:obj];
272 | }];
273 |
274 | }
275 | }
276 |
277 | - (UIButton *)addButton:(CGRect)frame title:(NSString *)title tag:(NSInteger)tag{
278 | UIButton *button = [[UIButton alloc] initWithFrame:frame];
279 | [button setTitle:title forState:UIControlStateNormal];
280 | button.titleLabel.font = [UIFont boldSystemFontOfSize:17];
281 | button.tag = tag;
282 | [button setTitleColor:STModalRGBA(220, 210, 200, 1) forState:UIControlStateNormal];
283 | [button setBackgroundImage:st_imageWithColor(STModalRGBA(135, 140, 145, 0.65)) forState:UIControlStateNormal];
284 | [button setBackgroundImage:st_imageWithColor(STModalRGBA(135, 140, 145, 0.45)) forState:UIControlStateHighlighted];
285 | [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
286 | [_containerView addSubview:button];
287 | [_buttons addObject:button];
288 | return button;
289 | }
290 |
291 | - (void)buttonClicked:(UIButton *)button{
292 | [self hide:YES];
293 | if (self.actionHandler){
294 | self.actionHandler(button.tag);
295 | }
296 | }
297 |
298 | #pragma mark - show / hide
299 |
300 | - (void)show:(BOOL)animated{
301 | [self prepareForShow];
302 | _modal.hideWhenTouchOutside = self.hideWhenTapOutside;
303 | _modal.didShowHandler = self.didShowHandler;
304 | _modal.didHideHandler = self.didHideHandler;
305 | [_modal show:animated];
306 | }
307 |
308 | - (void)hide:(BOOL)animated{
309 | [_modal hide:animated];
310 | }
311 |
312 | - (BOOL)onShow{
313 | return _modal.onShow;
314 | }
315 |
316 | @end
317 |
318 | @implementation STAlertView (Show)
319 |
320 | + (instancetype)showTitle:(NSString *)title
321 | image:(UIImage *)image
322 | message:(NSString *)message
323 | buttonTitles:(NSArray *)buttonTitles
324 | handler:(void (^)(NSInteger))handler{
325 | STAlertView *alert = [[STAlertView alloc] initWithTitle:title
326 | image:image
327 | message:message
328 | buttonTitles:buttonTitles];
329 | [alert setActionHandler:handler];
330 | [alert show:YES];
331 | return alert;
332 | }
333 |
334 | + (instancetype)showTitle:(NSString *)title
335 | message:(NSString *)message{
336 | STAlertView *alert = [[STAlertView alloc] initWithTitle:title
337 | image:nil
338 | message:message
339 | buttonTitles:nil];
340 | alert.hideWhenTapOutside = YES;
341 | [alert show:YES];
342 | return alert;
343 | }
344 |
345 | + (instancetype)showTitle:(NSString *)title
346 | message:(NSString *)message
347 | hideDelay:(CGFloat)delay{
348 | if (delay>0){
349 | STAlertView *alert = [self showTitle:title message:message];
350 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
351 | [alert hide:YES];
352 | });
353 | return alert;
354 | }
355 | return nil;
356 | }
357 |
358 | @end
359 |
--------------------------------------------------------------------------------
/STModalDemo/STModal/STActionSheet/STActionSheet.m:
--------------------------------------------------------------------------------
1 | //
2 | // STActionSheet.m
3 | // STModalDemo
4 | //
5 | // Created by zhenlintie on 15/6/6.
6 | // Copyright (c) 2015年 sTeven. All rights reserved.
7 | //
8 |
9 | #import "STActionSheet.h"
10 | #import "STModal.h"
11 | #import "STModalUtil.h"
12 |
13 | #define kSTSheetRadius 13
14 | #define kSTSheetSidePaddingV 8
15 | #define kSTSheetSidePaddingH 8
16 | #define kSTSheetContentPadding 8
17 | #define kSTSheetButtonHeight 44
18 | #define kSTSheetLineColor STModalRGBA(78, 78, 80, 1)
19 | #define kSTSheetBackColor STModalRGBA(150, 164, 168, 1)
20 | #define kSTSheetTitleColor STModalRGBA(242, 249, 255, 1)
21 |
22 | /**
23 | * 按钮容器
24 | */
25 | @interface STASContainerView : UIView
26 | @property (strong, nonatomic) UIView *containerView;
27 | @end
28 |
29 | @implementation STASContainerView
30 |
31 | - (instancetype)initWithFrame:(CGRect)frame{
32 | if (self = [super initWithFrame:frame]){
33 | self.layer.cornerRadius = kSTSheetRadius;
34 | self.layer.borderWidth = 0.5;
35 | self.layer.borderColor = kSTSheetLineColor.CGColor;
36 | // self.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.3].CGColor;
37 | // self.layer.shadowOffset = CGSizeZero;
38 | // self.layer.shadowOpacity = 0.3;
39 | // self.layer.shadowRadius = kSTSheetRadius*2;
40 |
41 | _containerView = [[UIView alloc] initWithFrame:CGRectZero];
42 | _containerView.layer.cornerRadius = kSTSheetRadius;
43 | _containerView.layer.masksToBounds = YES;
44 | _containerView.backgroundColor = kSTSheetBackColor;
45 | [self addSubview:_containerView];
46 | }
47 | return self;
48 | }
49 |
50 | - (void)addSubview:(UIView *)view{
51 | if (![view isEqual:_containerView] && ![view isKindOfClass:[UIToolbar class]]){
52 | [_containerView addSubview:view];
53 | return;
54 | }
55 | [super addSubview:view];
56 | }
57 |
58 | - (void)layoutSubviews{
59 | _containerView.frame = self.bounds;
60 | // self.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
61 | }
62 |
63 | @end
64 |
65 |
66 |
67 | @interface STASButton : UIButton
68 | @property (strong, nonatomic) STActionItem *item;
69 | @property (assign, nonatomic) CGFloat iconWidth;
70 | @property (assign, nonatomic) CGFloat iconPadding;
71 | @end
72 |
73 | @implementation STASButton
74 |
75 | - (instancetype)initWithFrame:(CGRect)frame{
76 | if (self = [super initWithFrame:frame]){
77 | [self setBackgroundImage:st_imageWithColor(STModalRGBA(120, 134, 138, 0.7)) forState:UIControlStateHighlighted];
78 | self.adjustsImageWhenHighlighted = NO;
79 | self.adjustsImageWhenDisabled = NO;
80 | self.titleLabel.textAlignment = NSTextAlignmentCenter;
81 | }
82 | return self;
83 | }
84 |
85 | - (void)setItem:(STActionItem *)item{
86 | _item = item;
87 | [self reloadData];
88 | }
89 |
90 | - (void)reloadData{
91 | if (_item.icon){
92 | [self setImage:_item.icon forState:UIControlStateNormal];
93 | self.imageView.contentMode = UIViewContentModeScaleAspectFit;
94 | }
95 | [self setAttributedTitle:_item.attributedTitle forState:UIControlStateNormal];
96 |
97 | }
98 |
99 | - (CGRect)imageRectForContentRect:(CGRect)contentRect{
100 | if (_item.icon){
101 | return CGRectMake(_iconPadding*(1.3), 0, _iconWidth, kSTSheetButtonHeight);
102 | }
103 | return CGRectZero;
104 | }
105 |
106 | - (CGRect)titleRectForContentRect:(CGRect)contentRect{
107 | if (_item.icon){
108 | return CGRectMake(_iconWidth+(1.3+0.4)*_iconPadding, 0, CGRectGetWidth(contentRect)-_iconWidth-(3)*_iconPadding, kSTSheetButtonHeight);
109 | }
110 | return self.bounds;
111 | }
112 |
113 | @end
114 |
115 |
116 | /**
117 | * 类似UIActionSheet
118 | */
119 | @interface STActionSheet ()
120 |
121 | @property (strong, nonatomic) STModal *modal;
122 |
123 | @property (strong, nonatomic) STASContainerView *topContainerView;
124 | @property (strong, nonatomic) UIScrollView *scrollView;
125 | @property (strong, nonatomic) UILabel *titleLabel;
126 | @property (strong, nonatomic) STASContainerView *cancelContainerView;
127 | @property (strong, nonatomic) STASButton *cancelButton;
128 | @property (strong, nonatomic) NSMutableArray *otherButtons;
129 | @property (strong, nonatomic) NSMutableArray *lines;
130 |
131 | @end
132 |
133 | @implementation STActionSheet{
134 | BOOL _didLayouted;
135 |
136 | CGSize _screenSize;
137 | CGFloat _otherButtonsHeight;
138 | CGFloat _maxTopContainerHeight;
139 | CGFloat _contentWidth;
140 | CGSize _buttonSize;
141 | }
142 |
143 | - (instancetype)initWithTitle:(NSString *)title
144 | cancelItem:(STActionItem *)cancelItem
145 | items:(NSArray *)items{
146 | if (self = [self initWithFrame:CGRectZero]){
147 | _title = title?[title copy]:nil;
148 | _cancelItem = cancelItem?[STActionItem itemWithAttributedTitle:cancelItem.attributedTitle icon:cancelItem.icon]:nil;
149 | _items = items?[NSArray arrayWithArray:items]:nil;
150 | }
151 | return self;
152 | }
153 |
154 | - (instancetype)initWithTitle:(NSString *)title
155 | cancelTitle:(NSString *)cancelTitle
156 | otherButtonTitles:(NSArray *)otherButtonTitles
157 | attribute:(NSDictionary *)attribute
158 | {
159 | if (self = [self initWithFrame:CGRectZero]){
160 | _title = title?[title copy]:nil;
161 | _cancelItem = cancelTitle?[STActionItem itemWithTitle:cancelTitle attribute:attribute]:nil;
162 | if (otherButtonTitles.count > 0){
163 | NSMutableArray *items = [NSMutableArray arrayWithCapacity:otherButtonTitles.count];
164 | for (NSString *otherTitle in otherButtonTitles){
165 | [items addObject:[STActionItem itemWithTitle:otherTitle attribute:attribute]];
166 | }
167 | _items = [NSArray arrayWithArray:items];
168 | }
169 | }
170 | return self;
171 | }
172 |
173 | - (instancetype)initWithFrame:(CGRect)frame{
174 | if (self = [super initWithFrame:CGRectZero]){
175 | [self loadData];
176 | [self loadUI];
177 | }
178 | return self;
179 | }
180 |
181 | - (void)loadData{
182 | _hideWhenTouchOutside = YES;
183 | _didLayouted = NO;
184 | _lines = [NSMutableArray new];
185 |
186 | self.modal = [STModal modalWithContentView:self];
187 | _modal.positionMode = STModelPositionCenterBottom;
188 | _modal.dimBackgroundWhenShow = YES;
189 | _modal.dimBackgroundColor = [UIColor colorWithWhite:0 alpha:0.1];
190 | [_modal setShowAnimation:[self showAnimation]];
191 | [_modal setHideAnimation:[self hideAnimation]];
192 |
193 | _screenSize = [UIScreen mainScreen].bounds.size;
194 | _contentWidth = _screenSize.width-2*kSTSheetSidePaddingH;
195 | _buttonSize = CGSizeMake(_contentWidth, kSTSheetButtonHeight);
196 | }
197 |
198 | - (void)loadUI{
199 | _topContainerView = [STASContainerView new];
200 | _scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
201 | [_topContainerView addSubview:_scrollView];
202 |
203 | _cancelContainerView = [[STASContainerView alloc] initWithFrame:CGRectMake(0, 0, _buttonSize.width, _buttonSize.height)];
204 | _cancelButton = [[STASButton alloc] initWithFrame:_cancelContainerView.bounds];
205 | [_cancelContainerView addSubview:_cancelButton];
206 | [_cancelButton addTarget:self action:@selector(cancelClicked:) forControlEvents:UIControlEventTouchUpInside];
207 |
208 | [self addSubview:_topContainerView];
209 | }
210 |
211 | #pragma mark - getter
212 |
213 | - (st_modal_animation)showAnimation{
214 | return ^CGFloat(){
215 | self.transform = CGAffineTransformMakeTranslation(0.0f, CGRectGetHeight(self.frame));
216 | CGFloat d = 0.35;
217 | [UIView animateWithDuration:d
218 | delay:0
219 | usingSpringWithDamping:1
220 | initialSpringVelocity:0
221 | options:UIViewAnimationOptionCurveEaseOut
222 | animations:^{
223 | self.transform = CGAffineTransformIdentity;
224 | }
225 | completion:^(BOOL finished) {
226 | }];
227 | return d;
228 | };
229 | }
230 |
231 | - (st_modal_animation)hideAnimation{
232 | return ^CGFloat(){
233 | CGFloat d = 0.3;
234 | [UIView animateWithDuration:d
235 | delay:0
236 | usingSpringWithDamping:1
237 | initialSpringVelocity:0
238 | options:UIViewAnimationOptionCurveEaseInOut
239 | animations:^{
240 | self.transform = CGAffineTransformMakeTranslation(0.0f, CGRectGetHeight(self.frame)+5);
241 | }
242 | completion:^(BOOL finished) {
243 | }];
244 | return d;
245 | };
246 | }
247 |
248 | #pragma mark - prepare for show
249 |
250 | - (void)reset{
251 | [_topContainerView removeFromSuperview];
252 | [_cancelContainerView removeFromSuperview];
253 | [_otherButtons makeObjectsPerformSelector:@selector(removeFromSuperview)];
254 | [_lines makeObjectsPerformSelector:@selector(removeFromSuperview)];
255 | [_lines removeAllObjects];
256 | [_otherButtons removeAllObjects];
257 | [_titleLabel removeFromSuperview];
258 | }
259 |
260 | - (void)prepareForShow{
261 | if (_didLayouted){
262 | return;
263 | }
264 | [self reset];
265 |
266 | CGFloat maxActionSheetHeight = _screenSize.height-kSTSheetSidePaddingV;
267 | CGFloat bottomPadding = kSTSheetSidePaddingV;
268 | CGFloat maxContentHeight = maxActionSheetHeight-bottomPadding;;
269 |
270 | CGFloat cancelHeight = _cancelItem?(kSTSheetButtonHeight):0;
271 | _maxTopContainerHeight = maxContentHeight-cancelHeight-(_cancelItem?kSTSheetSidePaddingV:0);
272 | _otherButtonsHeight = kSTSheetButtonHeight*_items.count;
273 | [self addCancelButton];
274 | [self addOtherButtons];
275 | [self addTitle];
276 |
277 | CGFloat titleBottom = _title?CGRectGetHeight(_titleLabel.frame)+2*kSTSheetContentPadding:0;
278 | CGFloat scrollHeight = MIN(_otherButtonsHeight, _maxTopContainerHeight-titleBottom);
279 |
280 | CGFloat contentPadding = (((scrollHeight+titleBottom)&&_cancelItem>0)?kSTSheetContentPadding:0);
281 | CGFloat totalHeight = MIN(maxActionSheetHeight, scrollHeight+titleBottom+cancelHeight+contentPadding+bottomPadding);
282 |
283 | self.frame = CGRectMake(kSTSheetSidePaddingH, _screenSize.height-totalHeight-kSTSheetSidePaddingH, _contentWidth,totalHeight);
284 | _topContainerView.frame = CGRectMake(0, 0, _contentWidth, scrollHeight+titleBottom);
285 | _scrollView.frame = CGRectMake(0, titleBottom, _contentWidth, scrollHeight);
286 | _scrollView.contentSize = CGSizeMake(_contentWidth, _otherButtonsHeight);
287 | _cancelContainerView.frame = CGRectMake(0, CGRectGetMaxY(_topContainerView.frame)+contentPadding, _buttonSize.width, _buttonSize.height);
288 |
289 | _didLayouted = YES;
290 | }
291 |
292 | - (void)addCancelButton{
293 | if (!_cancelItem){
294 | return;
295 | }
296 | [self addSubview:_cancelContainerView];
297 | _cancelButton.item = _cancelItem;
298 | }
299 |
300 | - (void)addOtherButtons{
301 | if (_items.count == 0){
302 | return;
303 | }
304 | if (!_otherButtons){
305 | _otherButtons = [NSMutableArray new];
306 | }
307 | [self addSubview:_topContainerView];
308 |
309 | CGFloat iconWidth = kSTSheetButtonHeight-2*kSTSheetContentPadding;
310 | CGFloat maxWidth = MIN([self maxOtherButtonsTitleWidth],_contentWidth-iconWidth-3*kSTSheetContentPadding);
311 | CGFloat top = 0;
312 | for (int i = 0; i < _items.count; i++){
313 | STASButton *button = [[STASButton alloc] initWithFrame:CGRectMake(0, top, _buttonSize.width, _buttonSize.height)];
314 | button.tag = i;
315 | button.item = _items[i];
316 | button.iconWidth = iconWidth;
317 | button.exclusiveTouch = YES;
318 | button.iconPadding = (_contentWidth-maxWidth-button.iconWidth)/3.0;
319 | [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
320 | [_scrollView addSubview:button];
321 | [_otherButtons addObject:button];
322 | [self addLine:CGRectMake(0, top, _buttonSize.width, 0.5) toView:self.scrollView];
323 |
324 | top += _buttonSize.height;
325 | }
326 | }
327 |
328 | - (void)addLine:(CGRect)frame toView:(UIView *)view{
329 | UIView *line = [[UIView alloc] initWithFrame:frame];
330 | line.backgroundColor = [kSTSheetLineColor colorWithAlphaComponent:0.25];
331 | [view addSubview:line];
332 | [_lines addObject:line];
333 | }
334 |
335 | - (void)addTitle{
336 | if (!_title){
337 | return;
338 | }
339 | if (!_titleLabel){
340 | _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, kSTSheetContentPadding, 0, 0)];
341 | _titleLabel.textColor = [kSTSheetTitleColor colorWithAlphaComponent:0.75];
342 | _titleLabel.font = [UIFont systemFontOfSize:14];
343 | _titleLabel.textAlignment = NSTextAlignmentCenter;
344 | _titleLabel.numberOfLines = 20;
345 | }
346 | [self addSubview:_topContainerView];
347 | [_topContainerView addSubview:_titleLabel];
348 | _titleLabel.text = _title;
349 | CGFloat titleWidth = _contentWidth-2*kSTSheetContentPadding;
350 | CGSize size = [_titleLabel sizeThatFits:CGSizeMake(titleWidth, 10000)];
351 | _titleLabel.frame = CGRectMake(kSTSheetContentPadding, kSTSheetContentPadding, titleWidth, size.height);
352 | }
353 |
354 | - (CGFloat)maxOtherButtonsTitleWidth{
355 | __block CGFloat width = 0;
356 | [_items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
357 | NSAttributedString *title = [(STActionItem *)obj attributedTitle];
358 | CGSize size = [title boundingRectWithSize:CGSizeMake(_contentWidth-kSTSheetContentPadding*2, kSTSheetButtonHeight) options:NSStringDrawingTruncatesLastVisibleLine context:nil].size;
359 | if (size.width > width){
360 | width = size.width;
361 | }
362 | }];
363 | return width;
364 | }
365 |
366 | #pragma mark - show / hide
367 |
368 | - (void)show:(BOOL)animated{
369 | [self prepareForShow];
370 | _modal.hideWhenTouchOutside = self.hideWhenTouchOutside;
371 | _modal.didShowHandler = self.didShowHandler;
372 | _modal.didHideHandler = self.didHideHandler;
373 | [_modal show:YES];
374 | }
375 |
376 | - (void)hide:(BOOL)animated{
377 | [_modal hide:YES];
378 | }
379 |
380 | #pragma mark - action
381 |
382 | - (void)buttonClicked:(UIButton *)button{
383 | if (_actionHandler){
384 | _actionHandler(_items[button.tag], button.tag);
385 | }
386 | [self hide:YES];
387 | }
388 |
389 | - (void)cancelClicked:(UIButton *)button{
390 | if (_didCancelHandler){
391 | _didCancelHandler(_cancelItem);
392 | }
393 | [self hide:YES];
394 | }
395 |
396 | @end
397 |
398 |
399 |
400 | @implementation STActionSheet (Show)
401 |
402 | + (instancetype)showTitle:(NSString *)title
403 | items:(NSArray *)items
404 | cancel:(STActionItem *)cancelItem{
405 | return [self showTitle:title items:items cancel:cancelItem actionHandler:nil cancelHandler:nil];
406 | }
407 |
408 | + (instancetype)showItems:(NSArray *)items actionHandler:(st_sheet_action_handler)actionHandler{
409 | return [self showTitle:nil items:items actionHandler:actionHandler];
410 | }
411 |
412 | + (instancetype)showTitle:(NSString *)title items:(NSArray *)items actionHandler:(st_sheet_action_handler)actionHandler{
413 | return [self showTitle:title items:items cancel:nil actionHandler:actionHandler cancelHandler:nil];
414 | }
415 |
416 | + (instancetype)showTitle:(NSString *)title
417 | items:(NSArray *)items
418 | cancel:(STActionItem *)cancelItem
419 | actionHandler:(st_sheet_action_handler)actionHandler
420 | cancelHandler:(void(^)(STActionItem *cancelItem))canceledHandler{
421 | STActionSheet *actionSheet = [[STActionSheet alloc] initWithTitle:title
422 | cancelItem:cancelItem
423 | items:items];
424 | [actionSheet setActionHandler:actionHandler];
425 | [actionSheet setDidCancelHandler:canceledHandler];
426 | [actionSheet show:YES];
427 | return actionSheet;
428 | }
429 |
430 | + (instancetype)showTitle:(NSString *)title
431 | otherButtonTitles:(NSArray *)otherButtonTitles
432 | cancel:(NSString *)cancelTitle
433 | attribute:(NSDictionary *)attribute{
434 | return [self showTitle:title otherButtonTitles:otherButtonTitles cancel:cancelTitle attribute:attribute actionHandler:nil cancelHandler:nil];
435 | }
436 |
437 | + (instancetype)showTitle:(NSString *)title
438 | otherButtonTitles:(NSArray *)otherButtonTitles
439 | cancel:(NSString *)cancelTitle
440 | attribute:(NSDictionary *)attribute
441 | actionHandler:(st_sheet_action_handler)actionHandler
442 | cancelHandler:(void(^)(STActionItem *cancelItem))canceledHandler{
443 | STActionSheet *actionSheet = [[STActionSheet alloc] initWithTitle:title
444 | cancelTitle:cancelTitle
445 | otherButtonTitles:otherButtonTitles
446 | attribute:attribute];
447 | [actionSheet setActionHandler:actionHandler];
448 | [actionSheet setDidCancelHandler:canceledHandler];
449 | [actionSheet show:YES];
450 | return actionSheet;
451 | }
452 |
453 | @end
454 |
455 |
456 | #pragma mark ##########################
457 |
458 | @implementation STActionItem{
459 | NSAttributedString *_customAttributedTitle;
460 | }
461 |
462 | /**
463 | * 快速生成
464 | */
465 | + (instancetype)itemWithTitle:(NSString *)title{
466 | return [self itemWithTitle:title icon:nil];
467 | }
468 |
469 | + (instancetype)itemWithTitle:(NSString *)title icon:(UIImage *)icon{
470 | return [[self alloc] initWithTitle:title icon:icon];
471 | }
472 |
473 | + (instancetype)itemWithAttributedTitle:(NSAttributedString *)attributedTitle{
474 | return [self itemWithAttributedTitle:attributedTitle icon:nil];
475 | }
476 |
477 | + (instancetype)itemWithAttributedTitle:(NSAttributedString *)attributedTitle icon:(UIImage *)icon{
478 | return [[self alloc] initWithAttributedTitle:attributedTitle icon:icon];
479 | }
480 |
481 | + (instancetype)itemWithTitle:(NSString *)title attribute:(NSDictionary *)attribute;{
482 | if (attribute){
483 | return [self itemWithAttributedTitle:[[NSAttributedString alloc] initWithString:title
484 | attributes:attribute]];
485 | }
486 | return [self itemWithTitle:title];
487 | }
488 |
489 | - (instancetype)initWithTitle:(NSString *)title icon:(UIImage *)icon{
490 | if (self = [super init]){
491 | _title = title;
492 | _icon = icon;
493 | }
494 | return self;
495 | }
496 |
497 | - (instancetype)initWithAttributedTitle:(NSAttributedString *)attributedTitle icon:(UIImage *)icon{
498 | if (self = [super init]){
499 | _customAttributedTitle = attributedTitle;
500 | _icon = icon;
501 | }
502 | return self;
503 | }
504 |
505 | - (NSAttributedString *)attributedTitle{
506 | if (_customAttributedTitle){
507 | return _customAttributedTitle;
508 | }
509 | else if (_title){
510 | return [[NSAttributedString alloc] initWithString:_title
511 | attributes:[self defaultAttribute]];
512 | }
513 | return nil;
514 | }
515 |
516 | - (NSDictionary *)defaultAttribute{
517 | return @{NSFontAttributeName:[UIFont systemFontOfSize:17],
518 | NSForegroundColorAttributeName:kSTSheetTitleColor};
519 | }
520 |
521 | @end
522 |
523 | @implementation STActionItem (Common)
524 |
525 | + (instancetype)desdructiveItem:(NSString *)title{
526 | return [self desdructiveItem:title icon:nil];
527 | }
528 |
529 | + (instancetype)desdructiveItem:(NSString *)title icon:(UIImage *)icon{
530 | NSAttributedString *attTitle = [[NSAttributedString alloc] initWithString:title
531 | attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:17],
532 | NSForegroundColorAttributeName:STModalRGBA(230, 10, 10, 1)}];
533 | return [self itemWithAttributedTitle:attTitle icon:icon];
534 | }
535 |
536 | @end
537 |
--------------------------------------------------------------------------------
/STModalDemo/STModalDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 9C90E3121B7DDC120064AB89 /* STFrontModal.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C90E3111B7DDC120064AB89 /* STFrontModal.m */; };
11 | 9CCAF58D1B21608600A7647F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCAF58C1B21608600A7647F /* main.m */; };
12 | 9CCAF5901B21608600A7647F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCAF58F1B21608600A7647F /* AppDelegate.m */; };
13 | 9CCAF5931B21608600A7647F /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCAF5921B21608600A7647F /* ViewController.m */; };
14 | 9CCAF5981B21608600A7647F /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9CCAF5971B21608600A7647F /* Images.xcassets */; };
15 | 9CCAF59B1B21608600A7647F /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9CCAF5991B21608600A7647F /* LaunchScreen.xib */; };
16 | 9CCAF5A71B21608600A7647F /* STModalDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCAF5A61B21608600A7647F /* STModalDemoTests.m */; };
17 | 9CCAF5B31B2160BB00A7647F /* STModal.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCAF5B21B2160BB00A7647F /* STModal.m */; };
18 | 9CCAF5B81B2178DF00A7647F /* STAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCAF5B71B2178DF00A7647F /* STAlertView.m */; };
19 | 9CCAF5BB1B21A04300A7647F /* AlertViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCAF5BA1B21A04300A7647F /* AlertViewController.m */; };
20 | 9CCAF5BF1B21AAE100A7647F /* lufei@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 9CCAF5BD1B21AAE100A7647F /* lufei@2x.jpg */; };
21 | 9CCAF5C01B21AAE100A7647F /* onepiece@2x.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 9CCAF5BE1B21AAE100A7647F /* onepiece@2x.jpeg */; };
22 | 9CCC338F1B25445C00B890F2 /* share_friend@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9CCC338D1B25445C00B890F2 /* share_friend@2x.png */; };
23 | 9CCC33901B25445C00B890F2 /* share_wechat@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9CCC338E1B25445C00B890F2 /* share_wechat@2x.png */; };
24 | 9CCC33931B2564BA00B890F2 /* STActionSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCC33921B2564BA00B890F2 /* STActionSheet.m */; };
25 | 9CCC33961B25675C00B890F2 /* ActionSheetViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCC33951B25675C00B890F2 /* ActionSheetViewController.m */; };
26 | 9CCC33991B25676400B890F2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9CCC33971B25676400B890F2 /* Main.storyboard */; };
27 | /* End PBXBuildFile section */
28 |
29 | /* Begin PBXContainerItemProxy section */
30 | 9CCAF5A11B21608600A7647F /* PBXContainerItemProxy */ = {
31 | isa = PBXContainerItemProxy;
32 | containerPortal = 9CCAF57F1B21608500A7647F /* Project object */;
33 | proxyType = 1;
34 | remoteGlobalIDString = 9CCAF5861B21608600A7647F;
35 | remoteInfo = STModalDemo;
36 | };
37 | /* End PBXContainerItemProxy section */
38 |
39 | /* Begin PBXFileReference section */
40 | 9C90E3101B7DDC120064AB89 /* STFrontModal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STFrontModal.h; sourceTree = ""; };
41 | 9C90E3111B7DDC120064AB89 /* STFrontModal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STFrontModal.m; sourceTree = ""; };
42 | 9CCAF5871B21608600A7647F /* STModalDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = STModalDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
43 | 9CCAF58B1B21608600A7647F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
44 | 9CCAF58C1B21608600A7647F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
45 | 9CCAF58E1B21608600A7647F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
46 | 9CCAF58F1B21608600A7647F /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
47 | 9CCAF5911B21608600A7647F /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
48 | 9CCAF5921B21608600A7647F /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
49 | 9CCAF5971B21608600A7647F /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
50 | 9CCAF59A1B21608600A7647F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
51 | 9CCAF5A01B21608600A7647F /* STModalDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = STModalDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
52 | 9CCAF5A51B21608600A7647F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
53 | 9CCAF5A61B21608600A7647F /* STModalDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STModalDemoTests.m; sourceTree = ""; };
54 | 9CCAF5B11B2160BB00A7647F /* STModal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STModal.h; sourceTree = ""; };
55 | 9CCAF5B21B2160BB00A7647F /* STModal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STModal.m; sourceTree = ""; };
56 | 9CCAF5B61B2178DF00A7647F /* STAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STAlertView.h; sourceTree = ""; };
57 | 9CCAF5B71B2178DF00A7647F /* STAlertView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STAlertView.m; sourceTree = ""; };
58 | 9CCAF5B91B21A04300A7647F /* AlertViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlertViewController.h; sourceTree = ""; };
59 | 9CCAF5BA1B21A04300A7647F /* AlertViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AlertViewController.m; sourceTree = ""; };
60 | 9CCAF5BD1B21AAE100A7647F /* lufei@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "lufei@2x.jpg"; sourceTree = ""; };
61 | 9CCAF5BE1B21AAE100A7647F /* onepiece@2x.jpeg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "onepiece@2x.jpeg"; sourceTree = ""; };
62 | 9CCB63841B248BA300F951AD /* STModalUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = STModalUtil.h; sourceTree = ""; };
63 | 9CCC338D1B25445C00B890F2 /* share_friend@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "share_friend@2x.png"; sourceTree = ""; };
64 | 9CCC338E1B25445C00B890F2 /* share_wechat@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "share_wechat@2x.png"; sourceTree = ""; };
65 | 9CCC33911B2564BA00B890F2 /* STActionSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STActionSheet.h; sourceTree = ""; };
66 | 9CCC33921B2564BA00B890F2 /* STActionSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STActionSheet.m; sourceTree = ""; };
67 | 9CCC33941B25675C00B890F2 /* ActionSheetViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionSheetViewController.h; sourceTree = ""; };
68 | 9CCC33951B25675C00B890F2 /* ActionSheetViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActionSheetViewController.m; sourceTree = ""; };
69 | 9CCC33981B25676400B890F2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
70 | /* End PBXFileReference section */
71 |
72 | /* Begin PBXFrameworksBuildPhase section */
73 | 9CCAF5841B21608600A7647F /* Frameworks */ = {
74 | isa = PBXFrameworksBuildPhase;
75 | buildActionMask = 2147483647;
76 | files = (
77 | );
78 | runOnlyForDeploymentPostprocessing = 0;
79 | };
80 | 9CCAF59D1B21608600A7647F /* Frameworks */ = {
81 | isa = PBXFrameworksBuildPhase;
82 | buildActionMask = 2147483647;
83 | files = (
84 | );
85 | runOnlyForDeploymentPostprocessing = 0;
86 | };
87 | /* End PBXFrameworksBuildPhase section */
88 |
89 | /* Begin PBXGroup section */
90 | 9C90E30F1B7DDC120064AB89 /* STFrontModal */ = {
91 | isa = PBXGroup;
92 | children = (
93 | 9C90E3101B7DDC120064AB89 /* STFrontModal.h */,
94 | 9C90E3111B7DDC120064AB89 /* STFrontModal.m */,
95 | );
96 | path = STFrontModal;
97 | sourceTree = "";
98 | };
99 | 9CCAF57E1B21608500A7647F = {
100 | isa = PBXGroup;
101 | children = (
102 | 9CCAF5B01B2160A100A7647F /* STModal */,
103 | 9CCAF5891B21608600A7647F /* STModalDemo */,
104 | 9CCAF5A31B21608600A7647F /* STModalDemoTests */,
105 | 9CCAF5881B21608600A7647F /* Products */,
106 | );
107 | sourceTree = "";
108 | };
109 | 9CCAF5881B21608600A7647F /* Products */ = {
110 | isa = PBXGroup;
111 | children = (
112 | 9CCAF5871B21608600A7647F /* STModalDemo.app */,
113 | 9CCAF5A01B21608600A7647F /* STModalDemoTests.xctest */,
114 | );
115 | name = Products;
116 | sourceTree = "";
117 | };
118 | 9CCAF5891B21608600A7647F /* STModalDemo */ = {
119 | isa = PBXGroup;
120 | children = (
121 | 9CCC33971B25676400B890F2 /* Main.storyboard */,
122 | 9CCAF5911B21608600A7647F /* ViewController.h */,
123 | 9CCAF5921B21608600A7647F /* ViewController.m */,
124 | 9CCAF5B91B21A04300A7647F /* AlertViewController.h */,
125 | 9CCAF5BA1B21A04300A7647F /* AlertViewController.m */,
126 | 9CCC33941B25675C00B890F2 /* ActionSheetViewController.h */,
127 | 9CCC33951B25675C00B890F2 /* ActionSheetViewController.m */,
128 | 9CCAF5BC1B21A05000A7647F /* res */,
129 | );
130 | path = STModalDemo;
131 | sourceTree = "";
132 | };
133 | 9CCAF58A1B21608600A7647F /* Supporting Files */ = {
134 | isa = PBXGroup;
135 | children = (
136 | 9CCAF58B1B21608600A7647F /* Info.plist */,
137 | 9CCAF58C1B21608600A7647F /* main.m */,
138 | );
139 | name = "Supporting Files";
140 | sourceTree = "";
141 | };
142 | 9CCAF5A31B21608600A7647F /* STModalDemoTests */ = {
143 | isa = PBXGroup;
144 | children = (
145 | 9CCAF5A61B21608600A7647F /* STModalDemoTests.m */,
146 | 9CCAF5A41B21608600A7647F /* Supporting Files */,
147 | );
148 | path = STModalDemoTests;
149 | sourceTree = "";
150 | };
151 | 9CCAF5A41B21608600A7647F /* Supporting Files */ = {
152 | isa = PBXGroup;
153 | children = (
154 | 9CCAF5A51B21608600A7647F /* Info.plist */,
155 | );
156 | name = "Supporting Files";
157 | sourceTree = "";
158 | };
159 | 9CCAF5B01B2160A100A7647F /* STModal */ = {
160 | isa = PBXGroup;
161 | children = (
162 | 9C90E30F1B7DDC120064AB89 /* STFrontModal */,
163 | 9CCB63831B248B8E00F951AD /* util */,
164 | 9CCAF5B41B21789100A7647F /* STActionSheet */,
165 | 9CCAF5B51B21789100A7647F /* STAlertView */,
166 | 9CCAF5B11B2160BB00A7647F /* STModal.h */,
167 | 9CCAF5B21B2160BB00A7647F /* STModal.m */,
168 | );
169 | path = STModal;
170 | sourceTree = "";
171 | };
172 | 9CCAF5B41B21789100A7647F /* STActionSheet */ = {
173 | isa = PBXGroup;
174 | children = (
175 | 9CCC33911B2564BA00B890F2 /* STActionSheet.h */,
176 | 9CCC33921B2564BA00B890F2 /* STActionSheet.m */,
177 | );
178 | path = STActionSheet;
179 | sourceTree = "";
180 | };
181 | 9CCAF5B51B21789100A7647F /* STAlertView */ = {
182 | isa = PBXGroup;
183 | children = (
184 | 9CCAF5B61B2178DF00A7647F /* STAlertView.h */,
185 | 9CCAF5B71B2178DF00A7647F /* STAlertView.m */,
186 | );
187 | path = STAlertView;
188 | sourceTree = "";
189 | };
190 | 9CCAF5BC1B21A05000A7647F /* res */ = {
191 | isa = PBXGroup;
192 | children = (
193 | 9CCC338D1B25445C00B890F2 /* share_friend@2x.png */,
194 | 9CCC338E1B25445C00B890F2 /* share_wechat@2x.png */,
195 | 9CCAF5BD1B21AAE100A7647F /* lufei@2x.jpg */,
196 | 9CCAF5BE1B21AAE100A7647F /* onepiece@2x.jpeg */,
197 | 9CCAF58A1B21608600A7647F /* Supporting Files */,
198 | 9CCAF58E1B21608600A7647F /* AppDelegate.h */,
199 | 9CCAF58F1B21608600A7647F /* AppDelegate.m */,
200 | 9CCAF5971B21608600A7647F /* Images.xcassets */,
201 | 9CCAF5991B21608600A7647F /* LaunchScreen.xib */,
202 | );
203 | name = res;
204 | sourceTree = "";
205 | };
206 | 9CCB63831B248B8E00F951AD /* util */ = {
207 | isa = PBXGroup;
208 | children = (
209 | 9CCB63841B248BA300F951AD /* STModalUtil.h */,
210 | );
211 | name = util;
212 | sourceTree = "";
213 | };
214 | /* End PBXGroup section */
215 |
216 | /* Begin PBXNativeTarget section */
217 | 9CCAF5861B21608600A7647F /* STModalDemo */ = {
218 | isa = PBXNativeTarget;
219 | buildConfigurationList = 9CCAF5AA1B21608600A7647F /* Build configuration list for PBXNativeTarget "STModalDemo" */;
220 | buildPhases = (
221 | 9CCAF5831B21608600A7647F /* Sources */,
222 | 9CCAF5841B21608600A7647F /* Frameworks */,
223 | 9CCAF5851B21608600A7647F /* Resources */,
224 | );
225 | buildRules = (
226 | );
227 | dependencies = (
228 | );
229 | name = STModalDemo;
230 | productName = STModalDemo;
231 | productReference = 9CCAF5871B21608600A7647F /* STModalDemo.app */;
232 | productType = "com.apple.product-type.application";
233 | };
234 | 9CCAF59F1B21608600A7647F /* STModalDemoTests */ = {
235 | isa = PBXNativeTarget;
236 | buildConfigurationList = 9CCAF5AD1B21608600A7647F /* Build configuration list for PBXNativeTarget "STModalDemoTests" */;
237 | buildPhases = (
238 | 9CCAF59C1B21608600A7647F /* Sources */,
239 | 9CCAF59D1B21608600A7647F /* Frameworks */,
240 | 9CCAF59E1B21608600A7647F /* Resources */,
241 | );
242 | buildRules = (
243 | );
244 | dependencies = (
245 | 9CCAF5A21B21608600A7647F /* PBXTargetDependency */,
246 | );
247 | name = STModalDemoTests;
248 | productName = STModalDemoTests;
249 | productReference = 9CCAF5A01B21608600A7647F /* STModalDemoTests.xctest */;
250 | productType = "com.apple.product-type.bundle.unit-test";
251 | };
252 | /* End PBXNativeTarget section */
253 |
254 | /* Begin PBXProject section */
255 | 9CCAF57F1B21608500A7647F /* Project object */ = {
256 | isa = PBXProject;
257 | attributes = {
258 | LastUpgradeCheck = 0630;
259 | ORGANIZATIONNAME = sTeven;
260 | TargetAttributes = {
261 | 9CCAF5861B21608600A7647F = {
262 | CreatedOnToolsVersion = 6.3.2;
263 | };
264 | 9CCAF59F1B21608600A7647F = {
265 | CreatedOnToolsVersion = 6.3.2;
266 | TestTargetID = 9CCAF5861B21608600A7647F;
267 | };
268 | };
269 | };
270 | buildConfigurationList = 9CCAF5821B21608500A7647F /* Build configuration list for PBXProject "STModalDemo" */;
271 | compatibilityVersion = "Xcode 3.2";
272 | developmentRegion = English;
273 | hasScannedForEncodings = 0;
274 | knownRegions = (
275 | en,
276 | Base,
277 | );
278 | mainGroup = 9CCAF57E1B21608500A7647F;
279 | productRefGroup = 9CCAF5881B21608600A7647F /* Products */;
280 | projectDirPath = "";
281 | projectRoot = "";
282 | targets = (
283 | 9CCAF5861B21608600A7647F /* STModalDemo */,
284 | 9CCAF59F1B21608600A7647F /* STModalDemoTests */,
285 | );
286 | };
287 | /* End PBXProject section */
288 |
289 | /* Begin PBXResourcesBuildPhase section */
290 | 9CCAF5851B21608600A7647F /* Resources */ = {
291 | isa = PBXResourcesBuildPhase;
292 | buildActionMask = 2147483647;
293 | files = (
294 | 9CCC33991B25676400B890F2 /* Main.storyboard in Resources */,
295 | 9CCC338F1B25445C00B890F2 /* share_friend@2x.png in Resources */,
296 | 9CCC33901B25445C00B890F2 /* share_wechat@2x.png in Resources */,
297 | 9CCAF59B1B21608600A7647F /* LaunchScreen.xib in Resources */,
298 | 9CCAF5C01B21AAE100A7647F /* onepiece@2x.jpeg in Resources */,
299 | 9CCAF5BF1B21AAE100A7647F /* lufei@2x.jpg in Resources */,
300 | 9CCAF5981B21608600A7647F /* Images.xcassets in Resources */,
301 | );
302 | runOnlyForDeploymentPostprocessing = 0;
303 | };
304 | 9CCAF59E1B21608600A7647F /* Resources */ = {
305 | isa = PBXResourcesBuildPhase;
306 | buildActionMask = 2147483647;
307 | files = (
308 | );
309 | runOnlyForDeploymentPostprocessing = 0;
310 | };
311 | /* End PBXResourcesBuildPhase section */
312 |
313 | /* Begin PBXSourcesBuildPhase section */
314 | 9CCAF5831B21608600A7647F /* Sources */ = {
315 | isa = PBXSourcesBuildPhase;
316 | buildActionMask = 2147483647;
317 | files = (
318 | 9CCC33931B2564BA00B890F2 /* STActionSheet.m in Sources */,
319 | 9CCAF5B31B2160BB00A7647F /* STModal.m in Sources */,
320 | 9C90E3121B7DDC120064AB89 /* STFrontModal.m in Sources */,
321 | 9CCAF5931B21608600A7647F /* ViewController.m in Sources */,
322 | 9CCAF5901B21608600A7647F /* AppDelegate.m in Sources */,
323 | 9CCC33961B25675C00B890F2 /* ActionSheetViewController.m in Sources */,
324 | 9CCAF5BB1B21A04300A7647F /* AlertViewController.m in Sources */,
325 | 9CCAF58D1B21608600A7647F /* main.m in Sources */,
326 | 9CCAF5B81B2178DF00A7647F /* STAlertView.m in Sources */,
327 | );
328 | runOnlyForDeploymentPostprocessing = 0;
329 | };
330 | 9CCAF59C1B21608600A7647F /* Sources */ = {
331 | isa = PBXSourcesBuildPhase;
332 | buildActionMask = 2147483647;
333 | files = (
334 | 9CCAF5A71B21608600A7647F /* STModalDemoTests.m in Sources */,
335 | );
336 | runOnlyForDeploymentPostprocessing = 0;
337 | };
338 | /* End PBXSourcesBuildPhase section */
339 |
340 | /* Begin PBXTargetDependency section */
341 | 9CCAF5A21B21608600A7647F /* PBXTargetDependency */ = {
342 | isa = PBXTargetDependency;
343 | target = 9CCAF5861B21608600A7647F /* STModalDemo */;
344 | targetProxy = 9CCAF5A11B21608600A7647F /* PBXContainerItemProxy */;
345 | };
346 | /* End PBXTargetDependency section */
347 |
348 | /* Begin PBXVariantGroup section */
349 | 9CCAF5991B21608600A7647F /* LaunchScreen.xib */ = {
350 | isa = PBXVariantGroup;
351 | children = (
352 | 9CCAF59A1B21608600A7647F /* Base */,
353 | );
354 | name = LaunchScreen.xib;
355 | sourceTree = "";
356 | };
357 | 9CCC33971B25676400B890F2 /* Main.storyboard */ = {
358 | isa = PBXVariantGroup;
359 | children = (
360 | 9CCC33981B25676400B890F2 /* Base */,
361 | );
362 | name = Main.storyboard;
363 | sourceTree = "";
364 | };
365 | /* End PBXVariantGroup section */
366 |
367 | /* Begin XCBuildConfiguration section */
368 | 9CCAF5A81B21608600A7647F /* Debug */ = {
369 | isa = XCBuildConfiguration;
370 | buildSettings = {
371 | ALWAYS_SEARCH_USER_PATHS = NO;
372 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
373 | CLANG_CXX_LIBRARY = "libc++";
374 | CLANG_ENABLE_MODULES = YES;
375 | CLANG_ENABLE_OBJC_ARC = YES;
376 | CLANG_WARN_BOOL_CONVERSION = YES;
377 | CLANG_WARN_CONSTANT_CONVERSION = YES;
378 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
379 | CLANG_WARN_EMPTY_BODY = YES;
380 | CLANG_WARN_ENUM_CONVERSION = YES;
381 | CLANG_WARN_INT_CONVERSION = YES;
382 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
383 | CLANG_WARN_UNREACHABLE_CODE = YES;
384 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
385 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
386 | COPY_PHASE_STRIP = NO;
387 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
388 | ENABLE_STRICT_OBJC_MSGSEND = YES;
389 | GCC_C_LANGUAGE_STANDARD = gnu99;
390 | GCC_DYNAMIC_NO_PIC = NO;
391 | GCC_NO_COMMON_BLOCKS = YES;
392 | GCC_OPTIMIZATION_LEVEL = 0;
393 | GCC_PREPROCESSOR_DEFINITIONS = (
394 | "DEBUG=1",
395 | "$(inherited)",
396 | );
397 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
398 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
399 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
400 | GCC_WARN_UNDECLARED_SELECTOR = YES;
401 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
402 | GCC_WARN_UNUSED_FUNCTION = YES;
403 | GCC_WARN_UNUSED_VARIABLE = YES;
404 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
405 | MTL_ENABLE_DEBUG_INFO = YES;
406 | ONLY_ACTIVE_ARCH = YES;
407 | SDKROOT = iphoneos;
408 | };
409 | name = Debug;
410 | };
411 | 9CCAF5A91B21608600A7647F /* Release */ = {
412 | isa = XCBuildConfiguration;
413 | buildSettings = {
414 | ALWAYS_SEARCH_USER_PATHS = NO;
415 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
416 | CLANG_CXX_LIBRARY = "libc++";
417 | CLANG_ENABLE_MODULES = YES;
418 | CLANG_ENABLE_OBJC_ARC = YES;
419 | CLANG_WARN_BOOL_CONVERSION = YES;
420 | CLANG_WARN_CONSTANT_CONVERSION = YES;
421 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
422 | CLANG_WARN_EMPTY_BODY = YES;
423 | CLANG_WARN_ENUM_CONVERSION = YES;
424 | CLANG_WARN_INT_CONVERSION = YES;
425 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
426 | CLANG_WARN_UNREACHABLE_CODE = YES;
427 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
428 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
429 | COPY_PHASE_STRIP = NO;
430 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
431 | ENABLE_NS_ASSERTIONS = NO;
432 | ENABLE_STRICT_OBJC_MSGSEND = YES;
433 | GCC_C_LANGUAGE_STANDARD = gnu99;
434 | GCC_NO_COMMON_BLOCKS = YES;
435 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
436 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
437 | GCC_WARN_UNDECLARED_SELECTOR = YES;
438 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
439 | GCC_WARN_UNUSED_FUNCTION = YES;
440 | GCC_WARN_UNUSED_VARIABLE = YES;
441 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
442 | MTL_ENABLE_DEBUG_INFO = NO;
443 | SDKROOT = iphoneos;
444 | VALIDATE_PRODUCT = YES;
445 | };
446 | name = Release;
447 | };
448 | 9CCAF5AB1B21608600A7647F /* Debug */ = {
449 | isa = XCBuildConfiguration;
450 | buildSettings = {
451 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
452 | INFOPLIST_FILE = STModalDemo/Info.plist;
453 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
454 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
455 | PRODUCT_NAME = "$(TARGET_NAME)";
456 | };
457 | name = Debug;
458 | };
459 | 9CCAF5AC1B21608600A7647F /* Release */ = {
460 | isa = XCBuildConfiguration;
461 | buildSettings = {
462 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
463 | INFOPLIST_FILE = STModalDemo/Info.plist;
464 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
465 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
466 | PRODUCT_NAME = "$(TARGET_NAME)";
467 | };
468 | name = Release;
469 | };
470 | 9CCAF5AE1B21608600A7647F /* Debug */ = {
471 | isa = XCBuildConfiguration;
472 | buildSettings = {
473 | BUNDLE_LOADER = "$(TEST_HOST)";
474 | FRAMEWORK_SEARCH_PATHS = (
475 | "$(SDKROOT)/Developer/Library/Frameworks",
476 | "$(inherited)",
477 | );
478 | GCC_PREPROCESSOR_DEFINITIONS = (
479 | "DEBUG=1",
480 | "$(inherited)",
481 | );
482 | INFOPLIST_FILE = STModalDemoTests/Info.plist;
483 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
484 | PRODUCT_NAME = "$(TARGET_NAME)";
485 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/STModalDemo.app/STModalDemo";
486 | };
487 | name = Debug;
488 | };
489 | 9CCAF5AF1B21608600A7647F /* Release */ = {
490 | isa = XCBuildConfiguration;
491 | buildSettings = {
492 | BUNDLE_LOADER = "$(TEST_HOST)";
493 | FRAMEWORK_SEARCH_PATHS = (
494 | "$(SDKROOT)/Developer/Library/Frameworks",
495 | "$(inherited)",
496 | );
497 | INFOPLIST_FILE = STModalDemoTests/Info.plist;
498 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
499 | PRODUCT_NAME = "$(TARGET_NAME)";
500 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/STModalDemo.app/STModalDemo";
501 | };
502 | name = Release;
503 | };
504 | /* End XCBuildConfiguration section */
505 |
506 | /* Begin XCConfigurationList section */
507 | 9CCAF5821B21608500A7647F /* Build configuration list for PBXProject "STModalDemo" */ = {
508 | isa = XCConfigurationList;
509 | buildConfigurations = (
510 | 9CCAF5A81B21608600A7647F /* Debug */,
511 | 9CCAF5A91B21608600A7647F /* Release */,
512 | );
513 | defaultConfigurationIsVisible = 0;
514 | defaultConfigurationName = Release;
515 | };
516 | 9CCAF5AA1B21608600A7647F /* Build configuration list for PBXNativeTarget "STModalDemo" */ = {
517 | isa = XCConfigurationList;
518 | buildConfigurations = (
519 | 9CCAF5AB1B21608600A7647F /* Debug */,
520 | 9CCAF5AC1B21608600A7647F /* Release */,
521 | );
522 | defaultConfigurationIsVisible = 0;
523 | defaultConfigurationName = Release;
524 | };
525 | 9CCAF5AD1B21608600A7647F /* Build configuration list for PBXNativeTarget "STModalDemoTests" */ = {
526 | isa = XCConfigurationList;
527 | buildConfigurations = (
528 | 9CCAF5AE1B21608600A7647F /* Debug */,
529 | 9CCAF5AF1B21608600A7647F /* Release */,
530 | );
531 | defaultConfigurationIsVisible = 0;
532 | defaultConfigurationName = Release;
533 | };
534 | /* End XCConfigurationList section */
535 | };
536 | rootObject = 9CCAF57F1B21608500A7647F /* Project object */;
537 | }
538 |
--------------------------------------------------------------------------------