├── Gifs
├── ipad.gif
├── portraitPhone.gif
└── landscapePhone.gif
├── Demo
└── BIPActionsheet
│ ├── BIPActionsheet
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── asCallIcon.imageset
│ │ │ ├── asCallIcon.png
│ │ │ ├── asCallIcon@2x.png
│ │ │ ├── asCallIcon@3x.png
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── ViewController.h
│ ├── AppDelegate.h
│ ├── main.m
│ ├── Info.plist
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── ViewController.m
│ └── AppDelegate.m
│ ├── BIPActionsheet.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── project.pbxproj
│ └── BIPActionsheetTests
│ ├── Info.plist
│ ├── BIPActionsheetTests.m
│ ├── BIPActionSheetStackTests.m
│ ├── BIPActionSheetItemTests.m
│ └── BIPActionSheetItemViewTests.m
├── Source
├── UIApplication+BIPActionSheet.h
├── UIView+BIPActionSheet.h
├── BIPActionSheetKit.h
├── UIImage+BIPActionSheet.h
├── UIWindow+BIPActionSheet.h
├── UIApplication+BIPActionSheet.m
├── UIView+BIPActionSheet.m
├── BIPActionSheetConstants.h
├── BIPActionSheetConstants.m
├── BIPActionSheetStack.h
├── UIImage+BIPActionSheet.m
├── UIWindow+BIPActionSheet.m
├── BIPActionSheetItem.h
├── BIPActionSheet.h
├── BIPActionSheetItemView.h
├── BIPActionSheetStack.m
├── BIPActionSheetItem.m
├── BIPActionSheetItemView.m
└── BIPActionSheet.m
├── BIPActionSheet.podspec
├── LICENSE
├── .gitignore
└── README.md
/Gifs/ipad.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Turkcell/BIPActionSheet/HEAD/Gifs/ipad.gif
--------------------------------------------------------------------------------
/Gifs/portraitPhone.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Turkcell/BIPActionSheet/HEAD/Gifs/portraitPhone.gif
--------------------------------------------------------------------------------
/Gifs/landscapePhone.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Turkcell/BIPActionSheet/HEAD/Gifs/landscapePhone.gif
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/Assets.xcassets/asCallIcon.imageset/asCallIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Turkcell/BIPActionSheet/HEAD/Demo/BIPActionsheet/BIPActionsheet/Assets.xcassets/asCallIcon.imageset/asCallIcon.png
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/Assets.xcassets/asCallIcon.imageset/asCallIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Turkcell/BIPActionSheet/HEAD/Demo/BIPActionsheet/BIPActionsheet/Assets.xcassets/asCallIcon.imageset/asCallIcon@2x.png
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/Assets.xcassets/asCallIcon.imageset/asCallIcon@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Turkcell/BIPActionSheet/HEAD/Demo/BIPActionsheet/BIPActionsheet/Assets.xcassets/asCallIcon.imageset/asCallIcon@3x.png
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 08/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/Source/UIApplication+BIPActionSheet.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIApplication+BIPActionSheet.h
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 08/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIApplication (BIPActionSheet)
12 |
13 | - (BOOL)bip_isLandscape;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Source/UIView+BIPActionSheet.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+BIPActionSheet.h
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 08/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIView (BIPActionSheet)
12 |
13 | - (CGFloat)bip_yOrigin;
14 | - (void)setBip_yOrigin:(CGFloat)yOrigin;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 08/07/2017.
6 | // Copyright © 2017 TURKCELL. 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 |
--------------------------------------------------------------------------------
/Source/BIPActionSheetKit.h:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheetKit.h
3 | // BIP
4 | //
5 | // Created by AHMET KAZIM GUNAY on 02/06/2017.
6 | // Copyright © 2017 Turkcell. All rights reserved.
7 | //
8 |
9 | #ifndef BIPActionSheetKit_h
10 | #define BIPActionSheetKit_h
11 |
12 | #import "BIPActionSheet.h"
13 | #import "BIPActionSheetItem.h"
14 | #import "BIPActionSheetItemView.h"
15 | #import "BIPActionSheetStack.h"
16 |
17 | #endif
18 |
--------------------------------------------------------------------------------
/Source/UIImage+BIPActionSheet.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+BIPActionSheet.h
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 08/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIImage (BIPActionSheet)
12 |
13 | + (UIImage *)bip_imageWithColor:(UIColor *)color;
14 | + (UIImage *)bip_imageWithColor:(UIColor *)color withFrame:(CGRect)frame;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 08/07/2017.
6 | // Copyright © 2017 TURKCELL. 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 |
--------------------------------------------------------------------------------
/Source/UIWindow+BIPActionSheet.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIWindow+BIPActionSheet.h
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 08/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIWindow (BIPActionSheet)
12 |
13 | + (UIWindow *)bip_windowWithLevel:(UIWindowLevel)windowLevel;
14 | + (CGFloat)bip_maxWindowLevelCurrently;
15 | + (UIEdgeInsets)safeAreaInset;
16 |
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/Source/UIApplication+BIPActionSheet.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIApplication+BIPActionSheet.m
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 08/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import "UIApplication+BIPActionSheet.h"
10 |
11 | @implementation UIApplication (BIPActionSheet)
12 |
13 | - (BOOL)bip_isLandscape
14 | {
15 | return UIInterfaceOrientationIsLandscape([self statusBarOrientation]);
16 | }
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/Assets.xcassets/asCallIcon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "asCallIcon.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "asCallIcon@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "asCallIcon@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Source/UIView+BIPActionSheet.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+BIPActionSheet.m
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 08/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import "UIView+BIPActionSheet.h"
10 |
11 | @implementation UIView (BIPActionSheet)
12 |
13 | - (CGFloat)bip_yOrigin
14 | {
15 | return CGRectGetMinY(self.frame);
16 | }
17 |
18 | - (void)setBip_yOrigin:(CGFloat)yOrigin
19 | {
20 | CGRect frame = self.frame;
21 | frame.origin.y = yOrigin;
22 | self.frame = frame;
23 | }
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/Source/BIPActionSheetConstants.h:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheetConstants.h
3 | // BIP
4 | //
5 | // Created by AHMET KAZIM GUNAY on 02/06/2017.
6 | // Copyright © 2017 Turkcell. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface BIPActionSheetConstants : NSObject
12 |
13 | extern CGFloat const kBIPActionSheetPaddingOffset;
14 | extern CGFloat const kBIPActionSheetPaddingOffsetiPAD;
15 | extern CGFloat const kBIPActionSheetBackgroundAlpha;
16 | extern CGFloat const kBIPActionSheetShowAnimationDuration;
17 | extern CGFloat const kBIPActionSheetHideAnimationDuration;
18 | extern CGFloat const kBIPActionSheetRowHeight;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/Source/BIPActionSheetConstants.m:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheetConstants.m
3 | // BIP
4 | //
5 | // Created by AHMET KAZIM GUNAY on 02/06/2017.
6 | // Copyright © 2017 Turkcell. All rights reserved.
7 | //
8 |
9 | #import "BIPActionSheetConstants.h"
10 |
11 | @implementation BIPActionSheetConstants
12 |
13 | CGFloat const kBIPActionSheetPaddingOffset = 10.f;
14 | CGFloat const kBIPActionSheetPaddingOffsetiPAD = 150.f;
15 | CGFloat const kBIPActionSheetBackgroundAlpha = 0.5;
16 | CGFloat const kBIPActionSheetShowAnimationDuration = 0.4;
17 | CGFloat const kBIPActionSheetHideAnimationDuration = 0.3;
18 | CGFloat const kBIPActionSheetRowHeight = 56.f;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/Source/BIPActionSheetStack.h:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheetStack.h
3 | // BIP
4 | //
5 | // Created by AHMET KAZIM GUNAY on 02/06/2017.
6 | // Copyright © 2017 Turkcell. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class BIPActionSheet;
12 |
13 | @interface BIPActionSheetStack : NSObject
14 |
15 | + (instancetype)sharedInstance;
16 |
17 | - (void)push:(BIPActionSheet *)actionSheet;
18 | - (void)pop:(BIPActionSheet *)actionSheet;
19 | - (void)pop:(BIPActionSheet *)actionSheet showNext:(BOOL)showNext;
20 |
21 | - (BOOL)containsActionSheetInStack:(BIPActionSheet *)actionsheet;
22 |
23 | @property (nonatomic, strong) NSMutableArray *actionSheets;
24 |
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheetTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/BIPActionSheet.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "BIPActionSheet"
3 | s.version = '1.0.1'
4 | s.summary = "Custom ActionSheet replacement with image support"
5 | s.description = <<-DESC
6 | Custom ActionSheet with image and text support, which is easy to use and modify. We developed to use in our BIP Messenger Application
7 | DESC
8 | s.homepage = "https://github.com/Turkcell/BIPActionSheet"
9 | s.license = 'MIT'
10 | s.author = { "Ahmet Kazım Günay" => "ahmetkgunay@gmail.com" }
11 | s.source = { :git => "https://github.com/Turkcell/BIPActionSheet.git", :tag => s.version.to_s }
12 | s.social_media_url = 'https://twitter.com/ahmtgny'
13 | s.platform = :ios, '7.0'
14 | s.requires_arc = true
15 |
16 | s.source_files = 'Source/*.{h,m}'
17 | end
18 |
--------------------------------------------------------------------------------
/Source/UIImage+BIPActionSheet.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+BIPActionSheet.m
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 08/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import "UIImage+BIPActionSheet.h"
10 |
11 | @implementation UIImage (BIPActionSheet)
12 |
13 | + (UIImage *)bip_imageWithColor:(UIColor *)color
14 | {
15 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
16 |
17 | return [[self class] bip_imageWithColor:color withFrame:rect];
18 | }
19 |
20 | + (UIImage *)bip_imageWithColor:(UIColor *)color withFrame:(CGRect)frame
21 | {
22 | UIGraphicsBeginImageContextWithOptions(frame.size, NO, 0.0);
23 | CGContextRef context = UIGraphicsGetCurrentContext();
24 |
25 | CGContextSetFillColorWithColor(context, [color CGColor]);
26 | CGContextFillRect(context, frame);
27 |
28 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
29 | UIGraphicsEndImageContext();
30 |
31 | return image;
32 | }
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Turkcell
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 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheetTests/BIPActionsheetTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionsheetTests.m
3 | // BIPActionsheetTests
4 | //
5 | // Created by AHMET KAZIM GUNAY on 12/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "BIPActionSheet.h"
11 |
12 | @interface BIPActionsheetTests : XCTestCase
13 |
14 | @end
15 |
16 | @implementation BIPActionsheetTests
17 |
18 | - (void)setUp {
19 | [super setUp];
20 |
21 | }
22 |
23 | - (void)testInitWithEmptyItems {
24 |
25 | BIPActionSheet *actionSheet = [[BIPActionSheet alloc] initWithItems:@[] cancelButtonTitle:@"Cancel" cancelHandler:nil];
26 | XCTAssertNotNil(actionSheet);
27 | }
28 |
29 | - (void)tearDown {
30 | // Put teardown code here. This method is called after the invocation of each test method in the class.
31 | [super tearDown];
32 | }
33 |
34 | - (void)testExample {
35 | // This is an example of a functional test case.
36 | // Use XCTAssert and related functions to verify your tests produce the correct results.
37 | }
38 |
39 | - (void)testPerformanceExample {
40 | // This is an example of a performance test case.
41 | [self measureBlock:^{
42 | // Put the code you want to measure the time of here.
43 | }];
44 | }
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/Source/UIWindow+BIPActionSheet.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIWindow+BIPActionSheet.m
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 08/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import "UIWindow+BIPActionSheet.h"
10 |
11 | @implementation UIWindow (BIPActionSheet)
12 |
13 | + (UIWindow *)bip_windowWithLevel:(UIWindowLevel)windowLevel
14 | {
15 | NSArray *windows = [[UIApplication sharedApplication] windows];
16 | for (UIWindow *window in windows)
17 | {
18 | if (window.windowLevel == windowLevel)
19 | {
20 | return window;
21 | }
22 | }
23 |
24 | return nil;
25 | }
26 |
27 | + (CGFloat)bip_maxWindowLevelCurrently
28 | {
29 | CGFloat maxWindowLevel = 0;
30 | NSArray * windows = [[UIApplication sharedApplication] windows];
31 |
32 | for (UIWindow * window in windows)
33 | {
34 | CGFloat currentWindowLevel = window.windowLevel;
35 |
36 | if (currentWindowLevel > maxWindowLevel)
37 | {
38 | maxWindowLevel = currentWindowLevel;
39 | }
40 | }
41 |
42 | return maxWindowLevel;
43 | }
44 |
45 | + (UIEdgeInsets)safeAreaInset
46 | {
47 | if(@available(iOS 11.0, *))
48 | {
49 | return [UIApplication sharedApplication].keyWindow.safeAreaInsets;
50 | }
51 | else
52 | {
53 | return UIEdgeInsetsZero;
54 | }
55 | }
56 |
57 | @end
58 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheetTests/BIPActionSheetStackTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheetStackTests.m
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 12/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "BIPActionSheetKit.h"
11 |
12 | @interface BIPActionSheetStackTests : XCTestCase
13 |
14 | @property (nonatomic, strong) BIPActionSheetStack *stack;
15 |
16 | @end
17 |
18 | @implementation BIPActionSheetStackTests
19 |
20 | #pragma mark - Setup
21 |
22 | - (void)setUp {
23 | [super setUp];
24 | // Put setup code here. This method is called before the invocation of each test method in the class.
25 | self.stack = [BIPActionSheetStack sharedInstance];
26 | }
27 |
28 | #pragma mark - Methods
29 |
30 | - (void)test_ContainsActionSheetInStack {
31 |
32 | BIPActionSheet *sheet = [BIPActionSheet showActionSheetWithItems:@[] cancelButtonTitle:@"Cancel" cancelHandler:nil];
33 | XCTAssertTrue([self.stack containsActionSheetInStack:sheet]);
34 | }
35 |
36 | #pragma mark - Tear Down
37 |
38 | - (void)tearDown {
39 | // Put teardown code here. This method is called after the invocation of each test method in the class.
40 | [super tearDown];
41 | }
42 |
43 | #pragma mark - Performance
44 |
45 | - (void)testPerformanceExample {
46 | // This is an example of a performance test case.
47 | [self measureBlock:^{
48 | // Put the code you want to measure the time of here.
49 | }];
50 | }
51 |
52 | @end
53 |
--------------------------------------------------------------------------------
/Source/BIPActionSheetItem.h:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheetItem.h
3 | // BIP
4 | //
5 | // Created by AHMET KAZIM GUNAY on 02/06/2017.
6 | // Copyright © 2017 Turkcell. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class BIPActionSheet;
12 |
13 | typedef void(^BIPActionSheetActionHandler)(BIPActionSheet *actionSheet);
14 |
15 | @interface BIPActionSheetItem : NSObject
16 |
17 | + (instancetype)itemWithTitle:(NSString *)title
18 | image:(UIImage *)image
19 | actionHandler:(BIPActionSheetActionHandler)actionHandler;
20 |
21 | + (instancetype)itemWithTitle:(NSString *)title
22 | image:(UIImage *)image
23 | textColor:(UIColor *)textColor
24 | actionHandler:(BIPActionSheetActionHandler)actionHandler;
25 |
26 | - (instancetype)initWithTitle:(NSString *)title
27 | image:(UIImage *)image
28 | actionHandler:(BIPActionSheetActionHandler)actionHandler;
29 |
30 | - (instancetype)initWithTitle:(NSString *)title
31 | image:(UIImage *)image
32 | textColor:(UIColor *)textColor
33 | actionHandler:(BIPActionSheetActionHandler)actionHandler;
34 |
35 |
36 | @property (nonatomic, copy) NSString *title;
37 | @property (nonatomic, strong) UIImage *image;
38 | @property (nonatomic, strong) UIColor *textColor;
39 |
40 | @property (nonatomic, copy) void (^actionHandler)(BIPActionSheet *actionSheet);
41 |
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | # CocoaPods
32 | #
33 | # We recommend against adding the Pods directory to your .gitignore. However
34 | # you should judge for yourself, the pros and cons are mentioned at:
35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
36 | #
37 | # Pods/
38 |
39 | # Carthage
40 | #
41 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
42 | # Carthage/Checkouts
43 |
44 | Carthage/Build
45 |
46 | # fastlane
47 | #
48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
49 | # screenshots whenever they are needed.
50 | # For more information about the recommended setup visit:
51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
52 |
53 | fastlane/report.xml
54 | fastlane/Preview.html
55 | fastlane/screenshots
56 | fastlane/test_output
57 |
58 | # Code Injection
59 | #
60 | # After new code Injection tools there's a generated folder /iOSInjectionProject
61 | # https://github.com/johnno1962/injectionforxcode
62 |
63 | iOSInjectionProject/
64 |
--------------------------------------------------------------------------------
/Source/BIPActionSheet.h:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheet.h
3 | // BIP
4 | //
5 | // Created by AHMET KAZIM GUNAY on 02/06/2017.
6 | // Copyright © 2017 Turkcell. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class BIPActionSheetItem;
12 |
13 | @interface BIPActionSheet : UIViewController
14 |
15 | - (instancetype)initWithItems:(NSArray *)items
16 | cancelButtonTitle:(NSString *)cancelButtonTitle
17 | cancelHandler:(void(^)(void))cancelHandler;
18 |
19 | - (instancetype)initWithTitle:(NSString *)title
20 | items:(NSArray *)items
21 | cancelButtonTitle:(NSString *)cancelButtonTitle
22 | cancelHandler:(void(^)(void))cancelHandler;
23 |
24 | + (instancetype)showActionSheetWithItems:(NSArray *)items
25 | cancelButtonTitle:(NSString *)cancelButtonTitle
26 | cancelHandler:(void(^)(void))cancelHandler;
27 |
28 | + (instancetype)showActionSheetWithTitle:(NSString *)title
29 | items:(NSArray *)items
30 | cancelButtonTitle:(NSString *)cancelButtonTitle
31 | cancelHandler:(void(^)(void))cancelHandler;
32 |
33 | - (void)show;
34 | - (void)hide;
35 |
36 | - (void)showInternal;
37 | - (void)dismiss;
38 |
39 | @property (nonatomic, assign, readonly, getter=isVisible) BOOL visible;
40 | @property (nonatomic, strong) UIButton *cancelButton;
41 |
42 | + (BOOL)isAnyActionsheetVisible;
43 | + (void)dismissVisibleActionsheet;
44 | + (void)dismissAllActionsheets;
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/Source/BIPActionSheetItemView.h:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheetItemView.h
3 | // BIP
4 | //
5 | // Created by AHMET KAZIM GUNAY on 02/06/2017.
6 | // Copyright © 2017 Turkcell. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef NS_ENUM(NSUInteger, BIPActionSheetImageAllignment) {
12 | Left,
13 | Right
14 | };
15 |
16 | @class BIPActionSheetItem, BIPActionSheet;
17 |
18 | @interface BIPActionSheetItemView : UIView
19 |
20 | /** Initialize with Item to show up */
21 |
22 | - (instancetype)initWithItem:(BIPActionSheetItem *)item
23 | isHeadlineItem:(BOOL)isHeadlineItem
24 | ownerSheet:(BIPActionSheet *)ownerSheet;
25 |
26 | /** Customize fonti color attributes using Apperance */
27 |
28 | @property (nonatomic, strong) UIFont *titleFont UI_APPEARANCE_SELECTOR; // defaults [UIFont systemFontOfSize:13.f]
29 |
30 | @property (nonatomic, strong) UIColor *titleTextColor UI_APPEARANCE_SELECTOR; // defaults [UIColor darkGrayColor]
31 |
32 | @property (nonatomic, strong) UIFont *itemFont UI_APPEARANCE_SELECTOR; // defaults [UIFont systemFontOfSize:18]
33 |
34 | @property (nonatomic, strong) UIColor *itemTextColor UI_APPEARANCE_SELECTOR; // defaults [UIColor darkGrayColor]
35 |
36 | @property (nonatomic, strong) UIFont *cancelButtonFont UI_APPEARANCE_SELECTOR; // defaults [UIFont boldSystemFontOfSize:18]
37 |
38 | @property (nonatomic, strong) UIColor *cancelButtonColor UI_APPEARANCE_SELECTOR; // defaults [UIColor redColor]
39 |
40 | @property (nonatomic, assign) BIPActionSheetImageAllignment imageAlignment UI_APPEARANCE_SELECTOR; // defaults Left
41 |
42 | @property (nonatomic, assign) CGFloat imageWidth UI_APPEARANCE_SELECTOR; // defaults 23.5
43 | @property (nonatomic, assign) CGFloat imageHeight UI_APPEARANCE_SELECTOR; // defaults 23.5
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | }
88 | ],
89 | "info" : {
90 | "version" : 1,
91 | "author" : "xcode"
92 | }
93 | }
--------------------------------------------------------------------------------
/Source/BIPActionSheetStack.m:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheetStack.m
3 | // BIP
4 | //
5 | // Created by AHMET KAZIM GUNAY on 02/06/2017.
6 | // Copyright © 2017 Turkcell. All rights reserved.
7 | //
8 |
9 | #import "BIPActionSheetStack.h"
10 | #import "BIPActionSheet.h"
11 | #import "BIPActionSheetConstants.h"
12 |
13 | @implementation BIPActionSheetStack
14 |
15 | #pragma mark - Initialize
16 |
17 | + (instancetype)sharedInstance
18 | {
19 | static BIPActionSheetStack *_sharedInstance = nil;
20 | static dispatch_once_t onceToken;
21 | dispatch_once(&onceToken, ^{
22 | _sharedInstance = [[BIPActionSheetStack alloc] init];
23 | _sharedInstance.actionSheets = [NSMutableArray array];
24 | });
25 |
26 | return _sharedInstance;
27 | }
28 |
29 | #pragma mark - Push / Pop Stacks
30 |
31 | - (void)push:(BIPActionSheet *)actionSheet
32 | {
33 | @synchronized (self) {
34 | [self.actionSheets addObject:actionSheet];
35 |
36 | if (self.actionSheets.count == 1)
37 | {
38 | [actionSheet showInternal];
39 | }
40 | }
41 | }
42 |
43 | - (void)pop:(BIPActionSheet *)actionSheet showNext:(BOOL)showNext
44 | {
45 | @synchronized (self) {
46 |
47 | [actionSheet hide];
48 | [self.actionSheets removeObject:actionSheet];
49 |
50 | if (showNext)
51 | {
52 | BIPActionSheet *last = [self.actionSheets lastObject];
53 |
54 | if (last)
55 | {
56 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kBIPActionSheetHideAnimationDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
57 | [last showInternal];
58 | });
59 | }
60 | }
61 | }
62 | }
63 |
64 | - (void)pop:(BIPActionSheet *)actionSheet
65 | {
66 | [self pop:actionSheet showNext:YES];
67 | }
68 |
69 | #pragma mark - Check Contains
70 |
71 | - (BOOL)containsActionSheetInStack:(BIPActionSheet *)actionsheet
72 | {
73 | return [self.actionSheets containsObject:actionsheet];
74 | }
75 |
76 | @end
77 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 08/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "BIPActionSheetKit.h"
11 |
12 | @interface ViewController ()
13 |
14 | @end
15 |
16 | @implementation ViewController
17 |
18 | - (void)viewDidLoad {
19 | [super viewDidLoad];
20 | }
21 |
22 | - (IBAction)btnTapped:(id)sender {
23 |
24 | BIPActionSheetItem *item = [BIPActionSheetItem itemWithTitle:@"Item1" image:[UIImage imageNamed:@"asCallIcon"] actionHandler:^(BIPActionSheet *actionSheet) {
25 |
26 | NSLog(@"Item1 Tapped");
27 | }];
28 |
29 | BIPActionSheetItem *item2 = [BIPActionSheetItem itemWithTitle:@"Item2" image:[UIImage imageNamed:@"asCallIcon"] textColor:[UIColor blackColor] actionHandler:^(BIPActionSheet *actionSheet) {
30 |
31 | NSLog(@"Item2 Tapped");
32 | }];
33 |
34 | BIPActionSheetItem *item3 = [BIPActionSheetItem itemWithTitle:@"Item3" image:[UIImage imageNamed:@"asCallIcon"] actionHandler:^(BIPActionSheet *actionSheet) {
35 |
36 | NSLog(@"Item3 Tapped");
37 | }];
38 |
39 | BIPActionSheetItem *item4 = [BIPActionSheetItem itemWithTitle:@"Item4" image:[UIImage imageNamed:@"asCallIcon"] actionHandler:^(BIPActionSheet *actionSheet) {
40 |
41 | NSLog(@"Item4 Tapped");
42 | }];
43 |
44 | BIPActionSheetItem *item5 = [BIPActionSheetItem itemWithTitle:@"Item5" image:[UIImage imageNamed:@"asCallIcon"] actionHandler:^(BIPActionSheet *actionSheet) {
45 |
46 | NSLog(@"Item5 Tapped");
47 | }];
48 |
49 | BIPActionSheetItem *item6 = [BIPActionSheetItem itemWithTitle:@"Item6" image:[UIImage imageNamed:@"asCallIcon"] actionHandler:^(BIPActionSheet *actionSheet) {
50 |
51 | NSLog(@"Item6 Tapped");
52 | }];
53 |
54 | [BIPActionSheet showActionSheetWithTitle:@"This is title" items:@[item, item2, item3, item4, item5, item6] cancelButtonTitle:@"Cancel" cancelHandler:^{
55 |
56 | NSLog(@"Cancel Tapped");
57 | }];
58 | }
59 |
60 | - (void)didReceiveMemoryWarning {
61 | [super didReceiveMemoryWarning];
62 | }
63 |
64 | @end
65 |
--------------------------------------------------------------------------------
/Source/BIPActionSheetItem.m:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheetItem.m
3 | // BIP
4 | //
5 | // Created by AHMET KAZIM GUNAY on 02/06/2017.
6 | // Copyright © 2017 Turkcell. All rights reserved.
7 | //
8 |
9 | #import "BIPActionSheetItem.h"
10 | #import "BIPActionSheetConstants.h"
11 |
12 | @implementation BIPActionSheetItem
13 |
14 | #pragma mark - Initialize
15 |
16 | - (instancetype)initWithTitle:(NSString *)title
17 | image:(UIImage *)image
18 | actionHandler:(BIPActionSheetActionHandler)actionHandler
19 | {
20 | if (self = [super init])
21 | {
22 | self.title = [title copy];
23 | self.image = image;
24 | self.actionHandler = actionHandler;
25 | }
26 | return self;
27 | }
28 |
29 | + (instancetype)itemWithTitle:(NSString *)title
30 | image:(UIImage *)image
31 | actionHandler:(BIPActionSheetActionHandler)actionHandler
32 | {
33 | return [[self alloc] initWithTitle:title
34 | image:image
35 | textColor:nil
36 | actionHandler:actionHandler];
37 | }
38 |
39 | - (instancetype)initWithTitle:(NSString *)title
40 | image:(UIImage *)image
41 | textColor:(UIColor *)textColor
42 | actionHandler:(BIPActionSheetActionHandler)actionHandler
43 | {
44 | if (self = [super init])
45 | {
46 | self.title = [title copy];
47 | self.image = image;
48 | self.textColor = textColor;
49 | self.actionHandler = actionHandler;
50 | }
51 | return self;
52 | }
53 |
54 | + (instancetype)itemWithTitle:(NSString *)title
55 | image:(UIImage *)image
56 | textColor:(UIColor *)textColor
57 | actionHandler:(BIPActionSheetActionHandler)actionHandler
58 | {
59 | return [[self alloc] initWithTitle:title
60 | image:image
61 | textColor:textColor
62 | actionHandler:actionHandler];
63 | }
64 |
65 | #pragma mark - NSCopying
66 |
67 | - (id)copyWithZone:(NSZone *)zone
68 | {
69 | BIPActionSheetItem *copyItem = [[self class] allocWithZone:zone];
70 |
71 | if (copyItem)
72 | {
73 | copyItem.title = self.title;
74 | copyItem.image = self.image;
75 | copyItem.textColor = self.textColor;
76 | copyItem.actionHandler = self.actionHandler;
77 | }
78 |
79 | return copyItem;
80 | }
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 08/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 | #import "BIPActionSheetKit.h"
11 |
12 | @interface AppDelegate ()
13 |
14 | @end
15 |
16 | @implementation AppDelegate
17 |
18 |
19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
20 | // Override point for customization after application launch.
21 |
22 | [[BIPActionSheetItemView appearance] setCancelButtonColor:[UIColor blueColor]];
23 | [[BIPActionSheetItemView appearance] setCancelButtonFont:[UIFont fontWithName:@"Helvetica-Bold" size:17]];
24 |
25 | [[BIPActionSheetItemView appearance] setItemFont:[UIFont fontWithName:@"Helvetica" size:17]];
26 | [[BIPActionSheetItemView appearance] setItemTextColor:[UIColor darkGrayColor]];
27 |
28 | [[BIPActionSheetItemView appearance] setTitleFont:[UIFont fontWithName:@"Helvetica" size:14]];
29 | [[BIPActionSheetItemView appearance] setTitleTextColor:[UIColor redColor]];
30 |
31 | [[BIPActionSheetItemView appearance] setImageAlignment:Left];
32 | [[BIPActionSheetItemView appearance] setImageHeight:30.f];
33 | [[BIPActionSheetItemView appearance] setImageWidth:30.f];
34 |
35 | return YES;
36 | }
37 |
38 |
39 | - (void)applicationWillResignActive:(UIApplication *)application {
40 | // 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.
41 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
42 | }
43 |
44 |
45 | - (void)applicationDidEnterBackground:(UIApplication *)application {
46 | // 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.
47 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
48 | }
49 |
50 |
51 | - (void)applicationWillEnterForeground:(UIApplication *)application {
52 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
53 | }
54 |
55 |
56 | - (void)applicationDidBecomeActive:(UIApplication *)application {
57 | // 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.
58 | }
59 |
60 |
61 | - (void)applicationWillTerminate:(UIApplication *)application {
62 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
63 | }
64 |
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheet/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheetTests/BIPActionSheetItemTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheetItemTests.m
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 12/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "BIPActionSheetItem.h"
11 |
12 | @interface BIPActionSheetItemTests : XCTestCase
13 |
14 | @property (nonatomic, copy) NSString *firstItemTitle;
15 | @property (nonatomic, strong) UIImage *firstItemImage;
16 | @property (nonatomic, copy) NSString *secondItemTitle;
17 | @property (nonatomic, strong) UIImage *secondItemImage;
18 | @property (nonatomic, strong) UIColor *firstItemTitleColor;
19 |
20 | @property (nonatomic, strong) BIPActionSheetItem *firstItem;
21 | @property (nonatomic, strong) BIPActionSheetItem *secondItem;
22 |
23 | @end
24 |
25 | @implementation BIPActionSheetItemTests
26 |
27 | - (void)setUp {
28 | [super setUp];
29 | // Put setup code here. This method is called before the invocation of each test method in the class.
30 |
31 | [self initializeItems];
32 | }
33 |
34 | - (void)initializeItems {
35 |
36 | _firstItemTitle = @"First";
37 | _secondItemTitle = @"Second";
38 |
39 | _firstItemImage = [UIImage imageNamed:@""];
40 | _secondItemImage = [UIImage imageNamed:@""];
41 |
42 | _firstItemTitleColor = [UIColor blueColor];
43 |
44 | _firstItem = [[BIPActionSheetItem alloc] initWithTitle:_firstItemTitle
45 | image:_firstItemImage
46 | textColor:_firstItemTitleColor
47 | actionHandler:nil];
48 |
49 | _secondItem = [BIPActionSheetItem itemWithTitle:_secondItemTitle
50 | image:_secondItemImage
51 | actionHandler:nil];
52 | }
53 |
54 | - (void)test_InitWithTitleWithColor {
55 |
56 | XCTAssertNotNil(_firstItem);
57 | }
58 |
59 | - (void)test_InitWithTitle {
60 |
61 | BIPActionSheetItem *item = [[BIPActionSheetItem alloc] initWithTitle:_firstItemTitle
62 | image:_firstItemImage
63 | actionHandler:nil];
64 | XCTAssertNotNil(item);
65 | }
66 |
67 | - (void)test_ItemWithClassMethod {
68 |
69 | XCTAssertNotNil(_secondItem);
70 | }
71 |
72 | - (void)test_ItemWithClassMethodWithColor {
73 |
74 | BIPActionSheetItem *item = [BIPActionSheetItem itemWithTitle:_secondItemTitle
75 | image:_secondItemImage
76 | textColor:[UIColor redColor]
77 | actionHandler:nil];
78 | XCTAssertNotNil(item);
79 | }
80 |
81 | - (void)test_ItemTitle {
82 |
83 | XCTAssertEqual(_firstItemTitle, _firstItem.title);
84 | }
85 |
86 | - (void)test_ItemImage {
87 |
88 | XCTAssertEqual(_firstItemImage, _firstItem.image);
89 | }
90 |
91 | - (void)test_ItemTextColor {
92 |
93 | XCTAssertEqual(_firstItemTitleColor, _firstItem.textColor);
94 | }
95 |
96 | - (void)test_CopyWithZone {
97 |
98 | BIPActionSheetItem *copyItem = [_firstItem copy];
99 | XCTAssertNotNil(copyItem);
100 | }
101 |
102 | - (void)test_TitleEqualsWithCopy {
103 |
104 | BIPActionSheetItem *copyItem = [_firstItem copy];
105 | XCTAssertEqual(_firstItem.title, copyItem.title);
106 | }
107 |
108 | - (void)test_TextColorEqualsWithCopy {
109 |
110 | BIPActionSheetItem *copyItem = [_firstItem copy];
111 | XCTAssertEqual(_firstItem.textColor, copyItem.textColor);
112 | }
113 |
114 | - (void)test_ImageEqualsWithCopy {
115 |
116 | BIPActionSheetItem *copyItem = [_firstItem copy];
117 | XCTAssertEqual(_firstItem.image, copyItem.image);
118 | }
119 |
120 | - (void)tearDown {
121 | // Put teardown code here. This method is called after the invocation of each test method in the class.
122 | _firstItem = nil;
123 | _secondItem = nil;
124 | _firstItemTitleColor = nil;
125 | _firstItemImage = nil;
126 | _firstItemTitle = nil;
127 | _secondItemImage = nil;
128 | _secondItemTitle = nil;
129 |
130 | [super tearDown];
131 | }
132 |
133 | - (void)testPerformanceExample {
134 | // This is an example of a performance test case.
135 | [self measureBlock:^{
136 | // Put the code you want to measure the time of here.
137 | }];
138 | }
139 |
140 | @end
141 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BIPActionSheet
2 | Custom ActionSheet with image and text support, which is easy to use and modify. We developed to use in our BIP Messenger Application
3 |
4 | #### Demo for iPhone
5 | 
6 | 
7 |
8 | #### Demo for iPad
9 | 
10 |
11 |
12 | ### Usage
13 |
14 | Usage is simple, just import "BIPActionSheetKit.h" to your class where you want to use this library.
15 |
16 | For example if you want to show actionsheet when button tapped:
17 |
18 | ```objective-c
19 |
20 | #import "BIPActionSheetKit.h"
21 |
22 | @implementation ViewController
23 |
24 | - (IBAction)btnTapped:(id)sender {
25 |
26 | BIPActionSheetItem *item = [BIPActionSheetItem itemWithTitle:@"Item1" image:[UIImage imageNamed:@"asCallIcon"] actionHandler:^(BIPActionSheet *actionSheet) {
27 |
28 | NSLog(@"Item1 Tapped");
29 | }];
30 |
31 | BIPActionSheetItem *item2 = [BIPActionSheetItem itemWithTitle:@"Item2" image:[UIImage imageNamed:@"asCallIcon"] textColor:[UIColor blackColor] actionHandler:^(BIPActionSheet *actionSheet) {
32 |
33 | NSLog(@"Item2 Tapped");
34 | }];
35 |
36 | BIPActionSheetItem *item3 = [BIPActionSheetItem itemWithTitle:@"Item3" image:[UIImage imageNamed:@"asCallIcon"] actionHandler:^(BIPActionSheet *actionSheet) {
37 |
38 | NSLog(@"Item3 Tapped");
39 | }];
40 |
41 | BIPActionSheetItem *item4 = [BIPActionSheetItem itemWithTitle:@"Item4" image:[UIImage imageNamed:@"asCallIcon"] actionHandler:^(BIPActionSheet *actionSheet) {
42 |
43 | NSLog(@"Item4 Tapped");
44 | }];
45 |
46 | BIPActionSheetItem *item5 = [BIPActionSheetItem itemWithTitle:@"Item5" image:[UIImage imageNamed:@"asCallIcon"] actionHandler:^(BIPActionSheet *actionSheet) {
47 |
48 | NSLog(@"Item5 Tapped");
49 | }];
50 |
51 | BIPActionSheetItem *item6 = [BIPActionSheetItem itemWithTitle:@"Item6" image:[UIImage imageNamed:@"asCallIcon"] actionHandler:^(BIPActionSheet *actionSheet) {
52 |
53 | NSLog(@"Item6 Tapped");
54 | }];
55 |
56 | [BIPActionSheet showActionSheetWithTitle:@"This is title" items:@[item, item2, item3, item4, item5, item6] cancelButtonTitle:@"Cancel" cancelHandler:^{
57 |
58 | NSLog(@"Cancel Tapped");
59 | }];
60 | }
61 |
62 | @end
63 | ```
64 | - You can check if actionsheet is visible with Actionsheet's public property
65 |
66 | ```objective-c
67 | @property (nonatomic, assign, readonly, getter=isVisible) BOOL visible;
68 | ```
69 |
70 |
71 | - You can easily control application-wide actionsheet controls with class methods of BIPActionSheet class
72 |
73 | ```objective-c
74 | + (BOOL)isAnyActionsheetVisible;
75 | + (void)dismissLastActiveActionsheet;
76 | + (void)dismissAllActionsheets;
77 | ```
78 |
79 | ### Appearence Support
80 |
81 | Application-wide appearence of Actionsheet can be set.
82 |
83 | NOTE: If you initialize BIPActionSheetItem with spesific text color, so this library firsly listens how you initialize the item to show up about appearence.
84 |
85 | For Example: You are initializing actionSheetItem with blueColor as shown below, Then this library firstly choose this item textColor as Blue regardless you initialized appearence with black color for spesific item.
86 |
87 | ```objective-c
88 | BIPActionSheetItem *item2 = [BIPActionSheetItem itemWithTitle:@"Item2" image:[UIImage imageNamed:@"asCallIcon"] textColor:[UIColor blueColor] actionHandler:^(BIPActionSheet *actionSheet) {
89 |
90 | NSLog(@"Item2 Tapped");
91 | }];
92 | ```
93 |
94 | ```objective-c
95 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
96 | // Override point for customization after application launch.
97 |
98 | [[BIPActionSheetItemView appearance] setCancelButtonColor:[UIColor blueColor]];
99 | [[BIPActionSheetItemView appearance] setCancelButtonFont:[UIFont fontWithName:@"Helvetica-Bold" size:17]];
100 |
101 | [[BIPActionSheetItemView appearance] setItemFont:[UIFont fontWithName:@"Helvetica" size:17]];
102 | [[BIPActionSheetItemView appearance] setItemTextColor:[UIColor darkGrayColor]];
103 |
104 | [[BIPActionSheetItemView appearance] setTitleFont:[UIFont fontWithName:@"Helvetica" size:14]];
105 | [[BIPActionSheetItemView appearance] setTitleTextColor:[UIColor redColor]];
106 |
107 | [[BIPActionSheetItemView appearance] setImageAlignment:Left];
108 | [[BIPActionSheetItemView appearance] setImageHeight:30.f];
109 | [[BIPActionSheetItemView appearance] setImageWidth:30.f];
110 |
111 | return YES;
112 | }
113 | ```
114 |
115 | ### Stack Design
116 |
117 | You can easily manage your app-wide actionsheets with stack design.
118 |
119 | For example: it is easy to check if spesific actionsheet is already presented with below method of BIPActionSheetStack global instance:
120 |
121 | ```objective-c
122 | - (BOOL)containsActionSheetInStack:(BIPActionSheet *)actionsheet;
123 | ```
124 |
125 | Anytime easy to access all actionsheets on stack with below property of BIPActionSheetStack global instance:
126 |
127 | ```objective-c
128 | @property (nonatomic, strong) NSMutableArray *actionSheets;
129 | ```
130 |
131 | ### Customize With Constants
132 |
133 | These constants are for UI Customization of BIPActionSheet Library as shown below:
134 | You can change them with needs of your project.
135 |
136 | ```objective-c
137 | @interface BIPActionSheetConstants : NSObject
138 |
139 | extern CGFloat const kBIPActionSheetPaddingOffset;
140 | extern CGFloat const kBIPActionSheetPaddingOffsetiPAD;
141 | extern CGFloat const kBIPActionSheetBackgroundAlpha;
142 | extern CGFloat const kBIPActionSheetShowAnimationDuration;
143 | extern CGFloat const kBIPActionSheetHideAnimationDuration;
144 | extern CGFloat const kBIPActionSheetRowHeight;
145 |
146 | @end
147 | ```
148 |
149 | For more information please check the Demo App.
150 |
151 | ## Installation
152 |
153 | There are two ways to use BIPActionSheet in your project:
154 | - using CocoaPods
155 | - by cloning the project into your repository
156 |
157 | ### Installation with CocoaPods
158 |
159 | [CocoaPods](http://cocoapods.org/) is a dependency manager for Swift and Objective-C, which automates and simplifies the process of using 3rd-party libraries in your projects. See the [Get Started](http://cocoapods.org/#get_started) section for more details.
160 |
161 | #### Podfile
162 | ```ruby
163 | platform :ios, '8.0'
164 | use_frameworks!
165 | pod 'BIPActionSheet', '~> 1.0.1'
166 | ```
167 |
168 | ## Requirements
169 |
170 | This library requires a deployment target of iOS 7.0 or greater.
171 |
172 |
173 | ## Author
174 |
175 | For any kind of question, you can easily access:
176 | - Ahmet Kazım Günay, ahmetkgunay@gmail.com
177 |
178 | ## License
179 |
180 | BIPActionSheet is available under the MIT license. See the LICENSE file for more info.
181 |
--------------------------------------------------------------------------------
/Source/BIPActionSheetItemView.m:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheetItemView.m
3 | // BIP
4 | //
5 | // Created by AHMET KAZIM GUNAY on 02/06/2017.
6 | // Copyright © 2017 Turkcell. All rights reserved.
7 | //
8 |
9 | #import "BIPActionSheetItemView.h"
10 | #import "BIPActionSheetItem.h"
11 | #import "BIPActionSheetConstants.h"
12 | #import "BIPActionSheet.h"
13 | #import "UIImage+BIPActionSheet.h"
14 |
15 | @interface BIPActionSheetItemView()
16 |
17 | @property (nonatomic, strong) UIImageView *imageView;
18 |
19 | @property (nonatomic, strong) UILabel *itemLabel;
20 | @property (nonatomic, strong) UILabel *titleLabel;
21 |
22 | @property (nonatomic, strong) UIButton *button;
23 | @property (nonatomic, strong) UIView *lineView;
24 | @property (nonatomic, strong) BIPActionSheetItem *item;
25 | @property (nonatomic, strong) BIPActionSheet *ownerActionSheet;
26 |
27 | @end
28 |
29 | @implementation BIPActionSheetItemView
30 |
31 | #pragma mark - Initialize
32 |
33 | - (instancetype)initWithItem:(BIPActionSheetItem *)item isHeadlineItem:(BOOL)isHeadlineItem ownerSheet:(BIPActionSheet *)ownerSheet
34 | {
35 | if (self = [super init])
36 | {
37 | self.item = item;
38 | self.ownerActionSheet = ownerSheet;
39 |
40 | self.imageView.image = item.image;
41 |
42 | if (item.textColor)
43 | {
44 | self.itemLabel.textColor = item.textColor;
45 | }
46 |
47 | [self addSubview:self.imageView];
48 |
49 | if (!isHeadlineItem) // no need to add button because title of actionsheet will not have any action handler
50 | {
51 | [self addSubview:self.button];
52 | [self addSubview:self.itemLabel];
53 | self.itemLabel.text = item.title;
54 | }
55 | else
56 | {
57 | [self addSubview:self.titleLabel];
58 | self.titleLabel.text = item.title;
59 | }
60 |
61 | [self addSubview:self.lineView];
62 |
63 | self.backgroundColor = [UIColor whiteColor];
64 | }
65 | return self;
66 | }
67 |
68 | #pragma mark - Lazy Initializers
69 |
70 | - (UIButton *)button
71 | {
72 | if (!_button)
73 | {
74 | _button = [UIButton buttonWithType:UIButtonTypeCustom];
75 | [_button setBackgroundImage:[UIImage bip_imageWithColor:[UIColor colorWithWhite:0 alpha:0.1]] forState:UIControlStateHighlighted];
76 | [_button setBackgroundImage:[UIImage bip_imageWithColor:[UIColor colorWithWhite:0 alpha:0.1]] forState:UIControlStateSelected];
77 | [_button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
78 | }
79 |
80 | return _button;
81 | }
82 |
83 | - (UILabel *)itemLabel
84 | {
85 | if (!_itemLabel)
86 | {
87 | _itemLabel = [[UILabel alloc] initWithFrame:CGRectZero];
88 | _itemLabel.textColor = [UIColor darkGrayColor];
89 | _itemLabel.backgroundColor = [UIColor clearColor];
90 | _itemLabel.font = [UIFont systemFontOfSize:18];
91 | }
92 |
93 | return _itemLabel;
94 | }
95 |
96 | - (UILabel *)titleLabel
97 | {
98 | if (!_titleLabel)
99 | {
100 | _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
101 | _titleLabel.backgroundColor = [UIColor clearColor];
102 | _titleLabel.font = [UIFont systemFontOfSize:13.f];
103 | _titleLabel.textColor = [UIColor darkGrayColor];
104 | _titleLabel.numberOfLines = 0.f;
105 | _titleLabel.adjustsFontSizeToFitWidth = YES;
106 | _titleLabel.minimumScaleFactor = 0.5;
107 | _titleLabel.textAlignment = NSTextAlignmentCenter;
108 | }
109 |
110 | return _titleLabel;
111 | }
112 |
113 | - (UIView *)lineView
114 | {
115 | if (!_lineView)
116 | {
117 | _lineView = [[UIView alloc] initWithFrame:CGRectZero];
118 | _lineView.backgroundColor = [UIColor lightGrayColor];
119 | _lineView.alpha = 0.2f;
120 | }
121 |
122 | return _lineView;
123 | }
124 |
125 | - (UIImageView *)imageView
126 | {
127 | if (!_imageView)
128 | {
129 | _imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
130 | _imageView.contentMode = UIViewContentModeScaleAspectFit;
131 | _imageView.clipsToBounds = YES;
132 | }
133 |
134 | return _imageView;
135 | }
136 |
137 | #pragma mark - Button Action
138 |
139 | - (void)buttonTapped:(UIButton *)sender
140 | {
141 | sender.selected = YES;
142 |
143 | [_ownerActionSheet dismiss];
144 |
145 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kBIPActionSheetHideAnimationDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
146 | if (_item.actionHandler)
147 | {
148 | _item.actionHandler(_ownerActionSheet);
149 | }
150 | });
151 | }
152 |
153 | #pragma mark - Appearence Setters
154 |
155 | - (void)setTitleFont:(UIFont *)titleFont
156 | {
157 | _titleFont = titleFont;
158 | _titleLabel.font = titleFont;
159 | }
160 |
161 | - (void)setItemFont:(UIFont *)itemFont
162 | {
163 | _itemFont = itemFont;
164 | _itemLabel.font = itemFont;
165 | }
166 |
167 | - (void)setItemTextColor:(UIColor *)itemTextColor
168 | {
169 | _itemTextColor = itemTextColor;
170 | _itemLabel.textColor = self.item.textColor ?: itemTextColor;
171 | }
172 |
173 | - (void)setTitleTextColor:(UIColor *)titleTextColor
174 | {
175 | _titleTextColor = titleTextColor;
176 | _titleLabel.textColor = titleTextColor;
177 | }
178 |
179 | - (void)setCancelButtonFont:(UIFont *)cancelButtonFont
180 | {
181 | _cancelButtonFont = cancelButtonFont;
182 | [_ownerActionSheet.cancelButton.titleLabel setFont:cancelButtonFont];
183 | }
184 |
185 | - (void)setCancelButtonColor:(UIColor *)cancelButtonColor
186 | {
187 | _cancelButtonColor = cancelButtonColor;
188 | [_ownerActionSheet.cancelButton setTitleColor:cancelButtonColor forState:UIControlStateNormal];
189 | }
190 |
191 | - (void)setImageAlignment:(BIPActionSheetImageAllignment)imageAlignment
192 | {
193 | _imageAlignment = imageAlignment;
194 |
195 | if (imageAlignment == Right) // defaults left
196 | {
197 | [self setNeedsLayout];
198 | }
199 | }
200 |
201 | - (void)setImageWidth:(CGFloat)imageWidth
202 | {
203 | _imageWidth = imageWidth;
204 | [self setNeedsLayout];
205 | }
206 |
207 | - (void)setImageHeight:(CGFloat)imageHeight
208 | {
209 | _imageHeight = imageHeight;
210 | [self setNeedsLayout];
211 | }
212 |
213 | #pragma mark - Layout
214 |
215 | - (void)layoutSubviews
216 | {
217 | [super layoutSubviews];
218 |
219 | CGFloat padding = 24.f;
220 | CGFloat lineViewHeight = 1.f;
221 | CGFloat imageHeight = self.imageHeight ?: 23.5;
222 | CGFloat imageWidth = self.imageWidth ?: 23.5;
223 |
224 | // imageView Frame
225 | CGRect imageViewRect = CGRectZero;
226 | imageViewRect.origin.x = self.imageAlignment == Left ? padding : self.frame.size.width - padding - imageWidth;
227 | imageViewRect.size.width = imageWidth;
228 | imageViewRect.size.height = imageHeight;
229 | imageViewRect.origin.y = (self.frame.size.height - imageViewRect.size.height) / 2;
230 | _imageView.frame = imageViewRect;
231 |
232 | // textlabel Frame
233 | CGRect textLabelRect = CGRectZero;
234 | textLabelRect.origin.x = self.imageAlignment == Left ? imageViewRect.origin.x + imageViewRect.size.width + padding : padding;
235 |
236 | if (_item.image == nil)
237 | {
238 | _itemLabel.textAlignment = NSTextAlignmentCenter;
239 | textLabelRect.origin.x = padding;
240 | }
241 |
242 | textLabelRect.size.width = self.frame.size.width - (textLabelRect.origin.x + padding);
243 | textLabelRect.origin.y = lineViewHeight;
244 | textLabelRect.size.height = self.frame.size.height - 2 * lineViewHeight;
245 | _itemLabel.frame = textLabelRect;
246 |
247 | _titleLabel.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
248 |
249 |
250 | // imageView Frame
251 | CGRect lineViewRect = CGRectZero;
252 | lineViewRect.origin.x = 0;
253 | lineViewRect.origin.y = self.frame.size.height - lineViewHeight;
254 | lineViewRect.size.width = self.frame.size.width;
255 | lineViewRect.size.height = lineViewHeight;
256 | _lineView.frame = lineViewRect;
257 |
258 | // button Frame
259 | _button.frame = self.bounds;
260 | }
261 |
262 | #pragma mark - NSCopying
263 |
264 | - (id)copyWithZone:(NSZone *)zone
265 | {
266 | BIPActionSheetItemView *copyItemView = [[self class] allocWithZone:zone];
267 |
268 | if (copyItemView)
269 | {
270 | copyItemView.imageView = self.imageView;
271 | copyItemView.itemLabel = self.itemLabel;
272 | copyItemView.button = self.button;
273 | copyItemView.lineView = self.lineView;
274 | copyItemView.item = [self.item copyWithZone:zone];
275 | copyItemView.ownerActionSheet = [self.ownerActionSheet copyWithZone:zone];
276 | copyItemView.imageAlignment = self.imageAlignment;
277 | copyItemView.titleLabel = self.titleLabel;
278 | copyItemView.imageWidth = self.imageWidth;
279 | copyItemView.imageHeight = self.imageHeight;
280 | }
281 |
282 | return copyItemView;
283 | }
284 |
285 | @end
286 |
--------------------------------------------------------------------------------
/Demo/BIPActionsheet/BIPActionsheetTests/BIPActionSheetItemViewTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheetItemViewTests.m
3 | // BIPActionsheet
4 | //
5 | // Created by AHMET KAZIM GUNAY on 12/07/2017.
6 | // Copyright © 2017 TURKCELL. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "BIPActionSheetItemView.h"
11 | #import "BIPActionSheetItem.h"
12 | #import "BIPActionSheetConstants.h"
13 |
14 | @interface BIPActionSheetItemViewTests : XCTestCase
15 |
16 | @property (nonatomic, copy) NSString *firstItemTitle;
17 | @property (nonatomic, copy) NSString *secondItemTitle;
18 | @property (nonatomic, strong) UIColor *firstItemTitleColor;
19 |
20 | @property (nonatomic, strong) BIPActionSheetItem *itemWithTextColor;
21 | @property (nonatomic, strong) BIPActionSheetItem *itemWithoutTextColor;
22 |
23 |
24 |
25 | @end
26 |
27 | @interface BIPActionSheetItemView (Testing)
28 |
29 | @property (nonatomic, strong) UIImageView *imageView;
30 |
31 | @property (nonatomic, strong) UILabel *itemLabel;
32 | @property (nonatomic, strong) UILabel *titleLabel;
33 |
34 | @property (nonatomic, strong) UIButton *button;
35 | @property (nonatomic, strong) UIView *lineView;
36 | @property (nonatomic, strong) BIPActionSheetItem *item;
37 | @property (nonatomic, strong) BIPActionSheet *ownerActionSheet;
38 |
39 | - (void)buttonTapped:(UIButton *)sender;
40 |
41 | @end
42 |
43 | @implementation BIPActionSheetItemViewTests
44 |
45 | - (void)setUp {
46 | [super setUp];
47 | // Put setup code here. This method is called before the invocation of each test method in the class.
48 | [self initializeItems];
49 | }
50 |
51 | - (void)initializeItems {
52 |
53 | _firstItemTitle = @"First";
54 | _secondItemTitle = @"Second";
55 |
56 | _firstItemTitleColor = [UIColor blueColor];
57 |
58 | _itemWithTextColor = [[BIPActionSheetItem alloc] initWithTitle:_firstItemTitle
59 | image:nil
60 | textColor:_firstItemTitleColor
61 | actionHandler:^(BIPActionSheet *actionSheet) {
62 | NSLog(@"Called Item With TextColor Handler");
63 | }];
64 |
65 | _itemWithoutTextColor = [BIPActionSheetItem itemWithTitle:_secondItemTitle
66 | image:nil
67 | actionHandler:^(BIPActionSheet *actionSheet) {
68 | NSLog(@"Called Item Without TextColor Handler");
69 | }];
70 | }
71 |
72 | - (void)test_InitializeWithItem {
73 |
74 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithoutTextColor isHeadlineItem:NO ownerSheet:nil];
75 | XCTAssertNotNil(itemView);
76 | }
77 |
78 | - (void)test_InitializeWithHeadLineItem {
79 |
80 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithoutTextColor isHeadlineItem:YES ownerSheet:nil];
81 | XCTAssertNotNil(itemView);
82 | }
83 |
84 | - (void)test_ItemViewContaintsTitleLabelIfHeadline {
85 |
86 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithoutTextColor isHeadlineItem:YES ownerSheet:nil];
87 | XCTAssertTrue([itemView.subviews containsObject:itemView.titleLabel]);
88 | }
89 |
90 | - (void)test_ItemViewNotContaintsTitleLabelIfHeadline {
91 |
92 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithoutTextColor isHeadlineItem:NO ownerSheet:nil];
93 | XCTAssertTrue(![itemView.subviews containsObject:itemView.titleLabel]);
94 | }
95 |
96 | #pragma mark - Test Appearences
97 |
98 | - (void)test_TitleTextColorAppearence {
99 |
100 | UIColor *titleColor = [UIColor yellowColor];
101 |
102 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithoutTextColor isHeadlineItem:YES ownerSheet:nil];
103 |
104 | [itemView setTitleTextColor:titleColor];
105 |
106 | XCTAssertTrue(CGColorEqualToColor(itemView.titleLabel.textColor.CGColor, titleColor.CGColor));
107 | }
108 |
109 | - (void)test_ItemTextColorAppearence {
110 |
111 | UIColor *itemColor = [UIColor blueColor];
112 |
113 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithoutTextColor isHeadlineItem:NO ownerSheet:nil];
114 |
115 | [itemView setItemTextColor:itemColor];
116 |
117 | XCTAssertTrue(CGColorEqualToColor(itemView.itemLabel.textColor.CGColor, itemColor.CGColor));
118 | }
119 |
120 | - (void)test_ItemTextColorAppearenceIfHeadline {
121 |
122 | // Should Be false because headline item doesnt have itemLabel
123 |
124 | UIColor *itemColor = [UIColor blueColor];
125 |
126 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithoutTextColor isHeadlineItem:YES ownerSheet:nil];
127 |
128 | [itemView setItemTextColor:itemColor];
129 |
130 | XCTAssertFalse(CGColorEqualToColor(itemView.itemLabel.textColor.CGColor, itemColor.CGColor));
131 | }
132 |
133 | - (void)test_ShouldHave_ItemTextColor_Not_AppearenceColor {
134 |
135 | // Should have color of which set while creating item as text color,
136 | // Appearence shouldn't work here because, developer has changed spesific item text color while initializing the item
137 |
138 | UIColor *itemColor = [UIColor yellowColor];
139 |
140 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithTextColor isHeadlineItem:NO ownerSheet:nil];
141 |
142 | [itemView setItemTextColor:itemColor];
143 |
144 | XCTAssertFalse(CGColorEqualToColor(itemView.itemLabel.textColor.CGColor, itemColor.CGColor));
145 | }
146 |
147 | - (void)test_ItemImageAlignmentAppearence {
148 |
149 | BIPActionSheetImageAllignment alignment = Right;
150 |
151 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithoutTextColor isHeadlineItem:YES ownerSheet:nil];
152 |
153 | [itemView setImageAlignment:alignment];
154 |
155 | XCTAssertEqual(itemView.imageAlignment, alignment);
156 | }
157 |
158 | - (void)test_CancelButtonFont {
159 |
160 | UIColor *cancelColor = [UIColor yellowColor];
161 |
162 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithoutTextColor isHeadlineItem:NO ownerSheet:nil];
163 |
164 | [itemView setCancelButtonColor:cancelColor];
165 |
166 | XCTAssertEqual(itemView.cancelButtonColor, cancelColor);
167 | }
168 |
169 | - (void)test_CancelButtonColor {
170 |
171 | UIFont *font = [UIFont fontWithName:@"Helvetica-Bold" size:14];
172 |
173 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithoutTextColor isHeadlineItem:NO ownerSheet:nil];
174 |
175 | [itemView setCancelButtonFont:font];
176 |
177 | XCTAssertEqual(itemView.cancelButtonFont, font);
178 | }
179 |
180 | - (void)test_ItemFont {
181 |
182 | UIFont *font = [UIFont fontWithName:@"Helvetica-Bold" size:14];
183 |
184 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithoutTextColor isHeadlineItem:NO ownerSheet:nil];
185 |
186 | [itemView setItemFont:font];
187 |
188 | XCTAssertEqual(itemView.itemFont, font);
189 | }
190 |
191 | - (void)test_TitleFont {
192 |
193 | UIFont *font = [UIFont fontWithName:@"Helvetica-Bold" size:14];
194 |
195 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithoutTextColor isHeadlineItem:NO ownerSheet:nil];
196 |
197 | [itemView setTitleFont:font];
198 |
199 | XCTAssertEqual(itemView.titleFont, font);
200 | }
201 |
202 | #pragma mark - Button Actions
203 |
204 | - (void)test_ButtonActionShouldCallHandler {
205 |
206 | XCTestExpectation *expectation = [self expectationWithDescription:@"Should Call Handler On Dismiss"];
207 |
208 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithoutTextColor isHeadlineItem:NO ownerSheet:nil];
209 |
210 | [itemView.item setActionHandler:^(BIPActionSheet *actionSheet){
211 |
212 | [expectation fulfill];
213 | }];
214 |
215 | [itemView buttonTapped:nil];
216 |
217 | [self waitForExpectationsWithTimeout:kBIPActionSheetHideAnimationDuration handler:^(NSError *error) {
218 | if (error) {
219 | NSLog(@"Timeout Error: %@", error);
220 | }
221 | }];
222 | }
223 |
224 | #pragma mark - Test Copy
225 |
226 | - (void)test_CopyWithZone {
227 |
228 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:_itemWithTextColor isHeadlineItem:YES ownerSheet:nil];
229 | BIPActionSheetItem *copyItemView = [itemView copy];
230 | XCTAssertNotNil(copyItemView);
231 | }
232 |
233 | #pragma mark - Tear Down
234 |
235 | - (void)tearDown {
236 | // Put teardown code here. This method is called after the invocation of each test method in the class.
237 |
238 | _itemWithTextColor = nil;
239 | _itemWithoutTextColor = nil;
240 | _firstItemTitleColor = nil;
241 | _firstItemTitle = nil;
242 | _secondItemTitle = nil;
243 |
244 | [super tearDown];
245 | }
246 |
247 | #pragma mark - Performance
248 |
249 | - (void)testPerformanceExample {
250 | // This is an example of a performance test case.
251 | [self measureBlock:^{
252 | // Put the code you want to measure the time of here.
253 | }];
254 | }
255 |
256 | @end
257 |
--------------------------------------------------------------------------------
/Source/BIPActionSheet.m:
--------------------------------------------------------------------------------
1 | //
2 | // BIPActionSheet.m
3 | // BIP
4 | //
5 | // Created by AHMET KAZIM GUNAY on 02/06/2017.
6 | // Copyright © 2017 Turkcell. All rights reserved.
7 | //
8 |
9 | #import "BIPActionSheet.h"
10 | #import "BIPActionSheetItem.h"
11 | #import "BIPActionSheetStack.h"
12 | #import "BIPActionSheetItemView.h"
13 | #import "BIPActionSheetConstants.h"
14 | #import "UIWindow+BIPActionSheet.h"
15 | #import "UIImage+BIPActionSheet.h"
16 | #import "UIView+BIPActionSheet.h"
17 | #import "UIApplication+BIPActionSheet.h"
18 |
19 | @interface BIPActionSheet()
20 |
21 | @property (nonatomic, strong) NSMutableArray *items;
22 | @property (nonatomic, strong) NSMutableArray *itemViews;
23 |
24 | @property (nonatomic, strong) UIWindow *actionSheetWindow;
25 | @property (nonatomic, strong) UIWindow *applicationWindow;
26 | @property (nonatomic, strong) UIScrollView *scrollView;
27 | @property (nonatomic, strong) UIView *containerView;
28 | @property (nonatomic, strong) UIView *backgroundView;
29 |
30 | @property (nonatomic, copy) NSString *cancelButtonTitle;
31 |
32 | @property (nonatomic, assign, readwrite, getter=isVisible) BOOL visible;
33 |
34 | @property (nonatomic, assign) CGFloat containerYOrigin;
35 | @property (nonatomic, assign) CGFloat cancelYOrigin;
36 | @property (nonatomic, assign) CGFloat contentViewHeight;
37 | @property (nonatomic, assign) CGFloat contentViewWidth;
38 | @property (nonatomic, assign) CGFloat paddingOffset;
39 |
40 | @property (nonatomic, copy) void (^inlineCancelHandler)(void);
41 |
42 | @property (nonatomic, strong) BIPActionSheetItemView *titleItemView;
43 |
44 | @property (nonatomic, assign) BOOL isStatusBarHiddenForRootViewController;
45 |
46 | @end
47 |
48 | @implementation BIPActionSheet
49 |
50 | static inline bool bip_isPad() {
51 |
52 | return ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad);
53 | }
54 |
55 | #pragma mark - Initialize
56 |
57 | - (instancetype)initWithTitle:(NSString *)title
58 | items:(NSArray *)items
59 | cancelButtonTitle:(NSString *)cancelButtonTitle
60 | cancelHandler:(void (^)(void))cancelHandler
61 | {
62 | if (self = [[BIPActionSheet alloc] initWithItems:items cancelButtonTitle:cancelButtonTitle cancelHandler:cancelHandler])
63 | {
64 | if (title.length)
65 | {
66 | BIPActionSheetItem *titleItem = [BIPActionSheetItem itemWithTitle:title image:nil actionHandler:nil];
67 | self.titleItemView = [[BIPActionSheetItemView alloc] initWithItem:titleItem isHeadlineItem:YES ownerSheet:self];
68 | [self.containerView addSubview:self.titleItemView];
69 | }
70 | }
71 | return self;
72 | }
73 |
74 | - (instancetype)initWithItems:(NSArray *)items
75 | cancelButtonTitle:(NSString *)cancelButtonTitle
76 | cancelHandler:(void (^)(void))cancelHandler
77 | {
78 | if (self = [super init])
79 | {
80 | self.inlineCancelHandler = cancelHandler;
81 | self.items = [NSMutableArray arrayWithArray:items];
82 | self.itemViews = [NSMutableArray arrayWithCapacity:items.count];
83 | self.cancelButtonTitle = cancelButtonTitle;
84 | self.applicationWindow = [UIWindow bip_windowWithLevel:UIWindowLevelNormal];
85 |
86 | for (BIPActionSheetItem *item in items)
87 | {
88 | BIPActionSheetItemView *itemView = [[BIPActionSheetItemView alloc] initWithItem:item isHeadlineItem:NO ownerSheet:self];
89 | [self.scrollView addSubview:itemView];
90 | [self.itemViews addObject:itemView];
91 | }
92 |
93 | [self.containerView addSubview:self.scrollView];
94 | [self.view addSubview:self.backgroundView];
95 | [self.view addSubview:self.containerView];
96 |
97 | if (!bip_isPad())
98 | {
99 | [self.view addSubview:self.cancelButton];
100 | }
101 |
102 | UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
103 | [self.backgroundView addGestureRecognizer:tgr];
104 | }
105 | return self;
106 | }
107 |
108 | #pragma mark - Tap Gesture
109 |
110 | - (void)tapped:(UITapGestureRecognizer *)recognizer
111 | {
112 | [self actionSheetCancelButtonTapped:self.cancelButton];
113 | }
114 |
115 | #pragma mark - Show ActionSheet
116 |
117 | + (instancetype)showActionSheetWithItems:(NSArray *)items
118 | cancelButtonTitle:(NSString *)cancelButtonTitle
119 | cancelHandler:(void(^)(void))cancelHandler;
120 | {
121 | BIPActionSheet *actionSheet = [[BIPActionSheet alloc] initWithItems:items
122 | cancelButtonTitle:cancelButtonTitle
123 | cancelHandler:cancelHandler];
124 | [actionSheet show];
125 |
126 | return actionSheet;
127 | }
128 |
129 | + (instancetype)showActionSheetWithTitle:(NSString *)title
130 | items:(NSArray *)items
131 | cancelButtonTitle:(NSString *)cancelButtonTitle
132 | cancelHandler:(void (^)(void))cancelHandler
133 | {
134 | BIPActionSheet *actionSheet = [[BIPActionSheet alloc] initWithTitle:title
135 | items:items
136 | cancelButtonTitle:cancelButtonTitle
137 | cancelHandler:cancelHandler];
138 | [actionSheet show];
139 |
140 | return actionSheet;
141 | }
142 |
143 | - (void)show
144 | {
145 | [[BIPActionSheetStack sharedInstance] push:self];
146 | }
147 |
148 | - (void)showInternal
149 | {
150 | dispatch_async(dispatch_get_main_queue(), ^{
151 |
152 | self.isStatusBarHiddenForRootViewController = self.applicationWindow.rootViewController.prefersStatusBarHidden;
153 |
154 | [self.actionSheetWindow setRootViewController:self];
155 | [self.actionSheetWindow makeKeyAndVisible];
156 | self.visible = YES;
157 |
158 | [UIView animateWithDuration:kBIPActionSheetShowAnimationDuration
159 | animations:^{
160 | self.backgroundView.alpha = kBIPActionSheetBackgroundAlpha;
161 | }
162 | ];
163 |
164 | if (!bip_isPad())
165 | {
166 | [UIView animateWithDuration:kBIPActionSheetShowAnimationDuration
167 | delay:kBIPActionSheetShowAnimationDuration / 2
168 | usingSpringWithDamping:0.6
169 | initialSpringVelocity:0.6
170 | options:UIViewAnimationOptionCurveEaseOut
171 | animations:^{
172 | self.cancelButton.bip_yOrigin = self.cancelYOrigin;
173 | }
174 | completion:^(BOOL finished) {
175 | //Completion Block
176 | }
177 | ];
178 |
179 | [UIView animateWithDuration:kBIPActionSheetShowAnimationDuration
180 | delay:0
181 | usingSpringWithDamping:0.6
182 | initialSpringVelocity:0.6
183 | options:UIViewAnimationOptionCurveEaseOut
184 | animations:^{
185 | self.containerView.bip_yOrigin = self.containerYOrigin;
186 | }
187 | completion:^(BOOL finished) {
188 | //Completion Block
189 | }
190 | ];
191 | }
192 | else
193 | {
194 | [self showAlertAnimation];
195 | }
196 |
197 | });
198 | }
199 |
200 | #pragma mark - Class Methods
201 |
202 | + (BOOL)isAnyActionsheetVisible
203 | {
204 | return [BIPActionSheetStack sharedInstance].actionSheets.count > 0;
205 | }
206 |
207 | + (void)dismissVisibleActionsheet
208 | {
209 | if ([self isAnyActionsheetVisible])
210 | {
211 | BIPActionSheet *as = [BIPActionSheetStack sharedInstance].actionSheets.lastObject;
212 | [as dismiss];
213 | }
214 | }
215 |
216 | + (void)dismissAllActionsheets
217 | {
218 | while ([BIPActionSheetStack sharedInstance].actionSheets.count > 0)
219 | {
220 | BIPActionSheet *as = [BIPActionSheetStack sharedInstance].actionSheets.lastObject;
221 | [[BIPActionSheetStack sharedInstance] pop:as showNext:NO];
222 | }
223 | }
224 |
225 | #pragma mark - Hide ActionSheet
226 |
227 | - (void)dismiss
228 | {
229 | [[BIPActionSheetStack sharedInstance] pop:self];
230 | }
231 |
232 | - (void)hide
233 | {
234 | dispatch_async(dispatch_get_main_queue(), ^{
235 |
236 | [UIView animateWithDuration:kBIPActionSheetHideAnimationDuration
237 | delay:0
238 | options:UIViewAnimationOptionCurveEaseInOut
239 | animations:^{
240 | self.backgroundView.alpha = 0;
241 | self.containerView.bip_yOrigin = self.view.frame.size.height;
242 | self.cancelButton.bip_yOrigin = self.view.frame.size.height;
243 | }
244 | completion:^(BOOL finished) {
245 | self.visible = NO;
246 | [self.actionSheetWindow removeFromSuperview];
247 | self.actionSheetWindow.rootViewController = nil;
248 | self.actionSheetWindow = nil;
249 | [self.applicationWindow makeKeyAndVisible];
250 | }
251 | ];
252 | });
253 | }
254 |
255 | #pragma mark - Layout
256 |
257 | - (void)viewWillLayoutSubviews
258 | {
259 | [super viewWillLayoutSubviews];
260 |
261 | self.backgroundView.frame = self.actionSheetWindow.bounds;
262 |
263 | if (!bip_isPad())
264 | {
265 | [self validateLayoutForiPhone];
266 | }
267 | else
268 | {
269 | [self validateLayoutForiPad];
270 | }
271 | }
272 |
273 | - (void)validateLayoutForiPhone
274 | {
275 | // cancelButton Frame
276 | CGRect cancelButtonRect = CGRectZero;
277 | cancelButtonRect.origin.x = self.paddingOffset;
278 | cancelButtonRect.size.width = self.contentViewWidth;
279 | cancelButtonRect.size.height = kBIPActionSheetRowHeight;
280 |
281 | // containerView Frame
282 | CGRect containerViewRect = CGRectZero;
283 | containerViewRect.origin.x = self.paddingOffset;
284 | containerViewRect.size.width = self.contentViewWidth;
285 | containerViewRect.size.height = self.contentViewHeight;
286 |
287 | if (self.isVisible)
288 | {
289 | cancelButtonRect.origin.y = self.cancelYOrigin;
290 | containerViewRect.origin.y = self.containerYOrigin;
291 | }
292 |
293 | self.cancelButton.frame = cancelButtonRect;
294 | self.containerView.frame = containerViewRect;
295 |
296 | self.scrollView.frame = [self isTitleViewExist] ? CGRectMake(0, kBIPActionSheetRowHeight, self.contentViewWidth, self.contentViewHeight - kBIPActionSheetRowHeight) : self.containerView.bounds;
297 |
298 | CGFloat contentHeight = self.items.count * kBIPActionSheetRowHeight;
299 | self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width, contentHeight);
300 |
301 | for (int i = 0; i