├── .gitignore
├── .swift-version
├── Example
├── LICENSE
├── NotchToolkit-Example.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ ├── NotchToolkit-Example.xcscheme
│ │ └── NotchToolkit.xcscheme
├── NotchToolkit-Example.xcworkspace
│ └── contents.xcworkspacedata
├── NotchToolkit-Example
│ ├── AppDelegate.swift
│ ├── Assets
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── pikachusquare.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── pikachusquare.png
│ │ │ └── spongebob.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── spongebob.png
│ │ └── tst_img.JPG
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── CornerOvalViewController.swift
│ ├── Info.plist
│ ├── NotchImageViewController.swift
│ └── ViewController.swift
├── NotchToolkit-ExampleTests
│ ├── Info.plist
│ └── NotchToolkit_ExampleTests.swift
├── NotchToolkit
│ ├── Cells
│ │ ├── NotchToolCell.swift
│ │ └── NotchToolNameIconCell.swift
│ ├── Classes
│ │ ├── NotchBar.swift
│ │ ├── NotchImageView.swift
│ │ └── NotchToolbar.swift
│ ├── Enumerations
│ │ ├── CurveSettings.swift
│ │ ├── DeviceOrientation.swift
│ │ ├── NotchMode.swift
│ │ ├── NotchScroll.swift
│ │ └── ToolIconTypes.swift
│ ├── Extenstions
│ │ ├── UIScreen+NotchFrame.swift
│ │ ├── UIScreen+NotchPositionMultiplier.swift
│ │ ├── UIScreen+iPhone10.swift
│ │ └── UIView+DrawNotch.swift
│ ├── Info.plist
│ ├── NotchToolkit.h
│ └── Protocols
│ │ └── NotchToolbarDelegate.swift
├── Podfile
├── Podfile.lock
└── Pods
│ ├── Local Podspecs
│ └── NotchToolkit.podspec.json
│ ├── Manifest.lock
│ ├── NotchToolkit
│ ├── LICENSE
│ ├── NotchToolkit
│ │ ├── Cells
│ │ │ └── NotchToolCell.swift
│ │ ├── Enumerators
│ │ │ ├── CurveSettings.swift
│ │ │ ├── DeviceOrientation.swift
│ │ │ ├── NotchMode.swift
│ │ │ └── NotchScroll.swift
│ │ ├── Extensions
│ │ │ ├── UIScreen+NotchFrame.swift
│ │ │ ├── UIScreen+NotchPositionMultiplier.swift
│ │ │ ├── UIScreen+iPhone10.swift
│ │ │ └── UIView+OvalOrCorners.swift
│ │ ├── NotchBar.swift
│ │ ├── NotchToolbar.swift
│ │ ├── NotchToolkit.h
│ │ └── Protocols
│ │ │ └── NotchToolbarDelegate.swift
│ └── README.md
│ ├── Pods.xcodeproj
│ └── project.pbxproj
│ └── Target Support Files
│ ├── NotchToolkit
│ ├── Info.plist
│ ├── NotchToolkit-dummy.m
│ ├── NotchToolkit-prefix.pch
│ ├── NotchToolkit-umbrella.h
│ ├── NotchToolkit.modulemap
│ └── NotchToolkit.xcconfig
│ ├── Pods-NotchToolkit-Example
│ ├── Info.plist
│ ├── Pods-NotchToolkit-Example-acknowledgements.markdown
│ ├── Pods-NotchToolkit-Example-acknowledgements.plist
│ ├── Pods-NotchToolkit-Example-dummy.m
│ ├── Pods-NotchToolkit-Example-frameworks.sh
│ ├── Pods-NotchToolkit-Example-resources.sh
│ ├── Pods-NotchToolkit-Example-umbrella.h
│ ├── Pods-NotchToolkit-Example.debug.xcconfig
│ ├── Pods-NotchToolkit-Example.modulemap
│ └── Pods-NotchToolkit-Example.release.xcconfig
│ └── Pods-NotchToolkit-ExampleTests
│ ├── Info.plist
│ ├── Pods-NotchToolkit-ExampleTests-acknowledgements.markdown
│ ├── Pods-NotchToolkit-ExampleTests-acknowledgements.plist
│ ├── Pods-NotchToolkit-ExampleTests-dummy.m
│ ├── Pods-NotchToolkit-ExampleTests-frameworks.sh
│ ├── Pods-NotchToolkit-ExampleTests-resources.sh
│ ├── Pods-NotchToolkit-ExampleTests-umbrella.h
│ ├── Pods-NotchToolkit-ExampleTests.debug.xcconfig
│ ├── Pods-NotchToolkit-ExampleTests.modulemap
│ └── Pods-NotchToolkit-ExampleTests.release.xcconfig
├── LICENSE
├── NotchToolkit.podspec
├── NotchToolkit.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ └── NotchToolkit.xcscheme
├── NotchToolkit
├── Cells
│ ├── NotchToolCell.swift
│ └── NotchToolNameIconCell.swift
├── Classes
│ ├── NotchBar.swift
│ ├── NotchImageView.swift
│ └── NotchToolbar.swift
├── Enumerations
│ ├── CurveSettings.swift
│ ├── DeviceOrientation.swift
│ ├── NotchMode.swift
│ ├── NotchScroll.swift
│ └── ToolIconTypes.swift
├── Extensions
│ ├── UIScreen+NotchFrame.swift
│ ├── UIScreen+NotchPositionMultiplier.swift
│ ├── UIScreen+iPhone10.swift
│ └── UIView+DrawNotch.swift
├── Info.plist
├── NotchToolkit.h
└── Protocols
│ └── NotchToolbarDelegate.swift
├── NotchToolkitTests
├── Info.plist
└── NotchToolkitTests.swift
├── README.md
└── drawNotch.gif
/.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 | ## Playgrounds
32 | timeline.xctimeline
33 | playground.xcworkspace
34 |
35 | # Swift Package Manager
36 | #
37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38 | # Packages/
39 | # Package.pins
40 | .build/
41 |
42 | # CocoaPods
43 | #
44 | # We recommend against adding the Pods directory to your .gitignore. However
45 | # you should judge for yourself, the pros and cons are mentioned at:
46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
47 | #
48 | # Pods/
49 |
50 | # Carthage
51 | #
52 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
53 | # Carthage/Checkouts
54 |
55 | Carthage/Build
56 |
57 | # fastlane
58 | #
59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
60 | # screenshots whenever they are needed.
61 | # For more information about the recommended setup visit:
62 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
63 |
64 | fastlane/report.xml
65 | fastlane/Preview.html
66 | fastlane/screenshots
67 | fastlane/test_output
68 |
--------------------------------------------------------------------------------
/.swift-version:
--------------------------------------------------------------------------------
1 | echo "4.0" > .swift-version
--------------------------------------------------------------------------------
/Example/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Ahmed Fathi Bekhit[me@ahmedbekhit.com]
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 |
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example.xcodeproj/xcshareddata/xcschemes/NotchToolkit-Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
34 |
40 |
41 |
42 |
43 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
66 |
68 |
74 |
75 |
76 |
77 |
78 |
79 |
85 |
87 |
93 |
94 |
95 |
96 |
98 |
99 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example.xcodeproj/xcshareddata/xcschemes/NotchToolkit.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
35 |
36 |
47 |
48 |
54 |
55 |
56 |
57 |
58 |
59 |
65 |
66 |
72 |
73 |
74 |
75 |
77 |
78 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // NotchToolkit-Example
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // 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.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // 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.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // 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.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // 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.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example/Assets/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 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example/Assets/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example/Assets/Assets.xcassets/pikachusquare.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "pikachusquare.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example/Assets/Assets.xcassets/pikachusquare.imageset/pikachusquare.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFathi/NotchToolkit/d8c0e69c440df88eb7f66103a6e01ebc24506f74/Example/NotchToolkit-Example/Assets/Assets.xcassets/pikachusquare.imageset/pikachusquare.png
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example/Assets/Assets.xcassets/spongebob.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "spongebob.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example/Assets/Assets.xcassets/spongebob.imageset/spongebob.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFathi/NotchToolkit/d8c0e69c440df88eb7f66103a6e01ebc24506f74/Example/NotchToolkit-Example/Assets/Assets.xcassets/spongebob.imageset/spongebob.png
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example/Assets/tst_img.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFathi/NotchToolkit/d8c0e69c440df88eb7f66103a6e01ebc24506f74/Example/NotchToolkit-Example/Assets/tst_img.JPG
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example/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 |
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example/CornerOvalViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CornerOvalViewController.swift
3 | // NotchToolkit-Example
4 | //
5 | // Created by Ahmed Bekhit on 9/26/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class CornerOvalViewController: UIViewController {
12 | @IBOutlet var aView: UIView!
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad()
16 |
17 | // Do any additional setup after loading the view.
18 | }
19 |
20 | override func didReceiveMemoryWarning() {
21 | super.didReceiveMemoryWarning()
22 | // Dispose of any resources that can be recreated.
23 | }
24 |
25 | @IBAction func drawOval(_ sender: UISegmentedControl) {
26 | if sender.selectedSegmentIndex == 0 {
27 | aView.draw(.oval, position: .right, curve: 1.5)
28 | }else if sender.selectedSegmentIndex == 1 {
29 | aView.draw(.oval, position: .left, curve: 1.5)
30 | }else if sender.selectedSegmentIndex == 2 {
31 | aView.draw(.oval, position: .top, curve: 1.5)
32 | }else if sender.selectedSegmentIndex == 3 {
33 | aView.draw(.oval, position: .bottom, curve: 1.5)
34 | }else if sender.selectedSegmentIndex == 4 {
35 | aView.draw(.oval, position: .horizontalSides, curve: 1.5)
36 | }else if sender.selectedSegmentIndex == 5 {
37 | aView.draw(.oval, position: .verticalSides, curve: 1.5)
38 | }else if sender.selectedSegmentIndex == 6 {
39 | aView.draw(.oval, position: .all, curve: 1.5)
40 | }
41 | }
42 | @IBAction func drawCorner(_ sender: UISegmentedControl) {
43 | if sender.selectedSegmentIndex == 0 {
44 | aView.draw(.corner, position: .right, curve: 35)
45 | }else if sender.selectedSegmentIndex == 1 {
46 | aView.draw(.corner, position: .left, curve: 35)
47 | }else if sender.selectedSegmentIndex == 2 {
48 | aView.draw(.corner, position: .top, curve: 35)
49 | }else if sender.selectedSegmentIndex == 3 {
50 | aView.draw(.corner, position: .bottom, curve: 35)
51 | }else if sender.selectedSegmentIndex == 4 {
52 | aView.draw(.corner, position: .diagonalAC, curve: 35)
53 | }else if sender.selectedSegmentIndex == 5 {
54 | aView.draw(.corner, position: .diagonalBD, curve: 35)
55 | }else if sender.selectedSegmentIndex == 6 {
56 | aView.draw(.corner, position: .all, curve: 35)
57 | }
58 | }
59 |
60 | @IBAction func dismissView(_ sender: UIButton) {
61 | self.dismiss(animated: true, completion:nil)
62 | }
63 | /*
64 | // MARK: - Navigation
65 |
66 | // In a storyboard-based application, you will often want to do a little preparation before navigation
67 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
68 | // Get the new view controller using segue.destinationViewController.
69 | // Pass the selected object to the new view controller.
70 | }
71 | */
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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 |
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example/NotchImageViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchImageViewController.swift
3 | // NotchToolkit-Example
4 | //
5 | // Created by Ahmed Bekhit on 11/8/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import NotchToolkit
11 |
12 | // MARK: - Implement NotchToolkit
13 |
14 | //Step 1. add `NotchToolbarDelegate`
15 | //Step 2. implement delegate functions, check NotchToolkit Delegates
16 |
17 | class NotchImageViewController: UIViewController {
18 | //Step 3. initialize `NotchImageView`
19 | var imageView: NotchImageView?
20 |
21 | override func viewDidLoad() {
22 | super.viewDidLoad()
23 | imageView = NotchImageView(image: UIImage(named:"tst_img.JPG"))
24 | }
25 |
26 | override func didReceiveMemoryWarning() {
27 | super.didReceiveMemoryWarning()
28 | }
29 |
30 | }
31 |
32 | // MARK: - NotchToolkit Delegate Methods
33 | extension NotchImageViewController: NotchToolbarDelegate {
34 | func deviceDidRotate() {
35 | //Step 5. call `autoResize` in the `deviceDidRotate` function
36 | imageView?.autoResize()
37 | }
38 |
39 | // This delegate function allows you to detect which toolbar icon was selected.
40 | func didTapToolIcon(_ tools: UICollectionView, toolIndex: IndexPath, section: Int, row: Int) {
41 | }
42 | }
43 |
44 | // MARK: - ViewController Buttons IBAction
45 | extension NotchImageViewController {
46 | @IBAction func loadNotchImage(_ sender: UIButton) {
47 | if !(imageView?.isVisible)! {
48 | sender.setTitle("Delete Image Object", for: .normal)
49 | imageView?.durationIntervals = 2.8
50 | imageView?.printBarColor = .red
51 | imageView?.printBarHeight = 5
52 | imageView?.delegate = self
53 | imageView?.prepare(in: self)
54 | imageView?.load()
55 | self.view.insertSubview(sender, aboveSubview: imageView!)
56 | }else{
57 | sender.setTitle("Load Image from Notch", for: .normal)
58 | imageView?.remove()
59 | imageView = NotchImageView(image: UIImage(named:"tst_img.JPG"))
60 | }
61 | }
62 |
63 | @IBAction func goBack(_ sender: UIButton) {
64 | self.dismiss(animated: true, completion: nil)
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Example/NotchToolkit-Example/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // NotchToolkit-Example
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import NotchToolkit
11 |
12 | // MARK: - Tool Icons Arrays
13 | extension ViewController {
14 | /**
15 | This is a custom array used to show more info when an icon is tapped
16 | */
17 | var iconListInfo:[String] {
18 | return ["Pika-Pikachu CHAAAAA", "AYYEE AYYEE CAPTAIN!","Just thinking, brb.", "Oh nerdy, my fav emoji.", "An iPhone compiling apps wirelessly.", "hacker", "hacker", "checklist", "sooooo liitttt"]
19 | }
20 |
21 | /**
22 | This array contains all the tool icons info.
23 | **NOTE**: an array of [UIImage, String] is displayed as one icon with the string content as a title.
24 | */
25 | var toolListIcons:[Any] {
26 | return [
27 | [UIImage(named:"pikachusquare")!, "Pikachu"],
28 | [UIImage(named:"spongebob")!, "Spongebob"],
29 | "🤔", "🤓",
30 | "📱", "👩💻",
31 | "👨💻", "✅",
32 | "🔥"]
33 | }
34 | }
35 |
36 | // MARK: - Implement NotchToolkit
37 |
38 | //Step 1. add `NotchToolbarDelegate`
39 | //Step 2. implement delegate functions, check NotchToolkit Delegates
40 |
41 | class ViewController: UIViewController {
42 |
43 | //Step 3. initialize `NotchToolbar`
44 | let toolbar = NotchToolbar()
45 |
46 | override func viewDidLoad() {
47 | super.viewDidLoad()
48 | //Step 4. setup `NotchToolbar` options
49 |
50 | //Set to true to make the toolbar visible initially--default is false.
51 | toolbar.notch.isVisible = false
52 |
53 | //Set the height of the NotchBar--default is 250.
54 | toolbar.notch.height = 250
55 |
56 | //`toolList` array accepts Strings, UIImage or an array of both types
57 | toolbar.iconWithNameFont = UIFont(name: "Avenir-Medium", size: 10.0)!
58 | toolbar.toolList = toolListIcons
59 |
60 | toolbar.delegate = self
61 | toolbar.prepare(in: self)
62 | }
63 |
64 | override func didReceiveMemoryWarning() {
65 | super.didReceiveMemoryWarning()
66 | // Dispose of any resources that can be recreated.
67 | }
68 | }
69 |
70 | // MARK: - NotchToolkit Delegate Methods
71 | extension ViewController: NotchToolbarDelegate {
72 | func deviceDidRotate() {
73 | //Step 5. call `autoResize` in the `deviceDidRotate` function
74 | toolbar.autoResize()
75 | }
76 |
77 | // This delegate function allows you to detect which toolbar icon was selected.
78 | func didTapToolIcon(_ tools: UICollectionView, toolIndex: IndexPath, section: Int, row: Int) {
79 | let alert = UIAlertController(title: "NotchToolkit Alert", message: iconListInfo[row], preferredStyle: UIAlertControllerStyle.alert)
80 | alert.addAction(UIAlertAction(title: "👍", style: UIAlertActionStyle.cancel, handler: {
81 | (UIAlertAction)in
82 | }))
83 | self.present(alert, animated: true, completion: nil)
84 | }
85 | }
86 |
87 | // MARK: - ViewController Buttons IBAction
88 | extension ViewController {
89 | @IBAction func showAction(_ sender: UIButton) {
90 | if toolbar.notch.isVisible {
91 | sender.setTitle("Show Notch Toolbar", for: .normal)
92 | }else{
93 | sender.setTitle("Hide Notch Toolbar", for: .normal)
94 | }
95 | toolbar.showOrHide()
96 |
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/Example/NotchToolkit-ExampleTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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 |
--------------------------------------------------------------------------------
/Example/NotchToolkit-ExampleTests/NotchToolkit_ExampleTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolkit_ExampleTests.swift
3 | // NotchToolkit-ExampleTests
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import NotchToolkit_Example
11 |
12 | class NotchToolkit_ExampleTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Cells/NotchToolCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolCell.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class NotchToolCell: UICollectionViewCell {
12 | private var toolIcon : UIImageView?
13 | private var toolTitle : UILabel?
14 |
15 | func setIcon(_ image:UIImage?) {
16 | if toolIcon == nil {
17 | toolIcon = UIImageView()
18 | toolIcon?.frame = CGRect(x: 0, y:0, width: contentView.frame.width, height: contentView.frame.height)
19 | toolIcon?.contentMode = .scaleAspectFit
20 | contentView.addSubview(toolIcon!)
21 | }
22 |
23 | if let icon = toolIcon {
24 | if let img = image {
25 | icon.image = img
26 | }
27 | icon.isHidden = false
28 | }
29 | if let title = toolTitle {
30 | title.isHidden = true
31 | }
32 | }
33 |
34 | func setTitle(_ text:String, font:UIFont, color:UIColor) {
35 | if toolTitle == nil {
36 | toolTitle = UILabel()
37 | toolTitle?.frame = CGRect(x: 0, y: 0, width: contentView.frame.width, height: contentView.frame.height)
38 | toolTitle?.font = font
39 | toolTitle?.textColor = color
40 | toolTitle?.textAlignment = .center
41 | contentView.addSubview(toolTitle!)
42 | }
43 |
44 | if let title = toolTitle {
45 | title.text = text
46 | title.isHidden = false
47 | }
48 |
49 | if let icon = toolIcon {
50 | icon.isHidden = true
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Cells/NotchToolNameIconCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolNameIconCell.swift
3 | // NotchToolkit
4 | //
5 | // Created by Ahmed Bekhit on 9/28/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class NotchToolNameIconCell: UICollectionViewCell {
12 | private var toolIcon : UIImageView?
13 | private var toolTitle : UILabel?
14 |
15 | func set(_ image:UIImage? = nil, text:String? = nil, font:UIFont? = nil, color:UIColor? = nil, type: toolIconTypes) {
16 | var titleFrame:CGRect!
17 | var iconFrame:CGRect!
18 |
19 | var isTitleHidden:Bool!
20 | var isIconHidden:Bool!
21 |
22 | switch type {
23 | case .image:
24 | titleFrame = CGRect(x: 0, y: 0, width: contentView.frame.width, height: contentView.frame.height)
25 | iconFrame = CGRect(x: 0, y: 0, width: contentView.frame.width, height: contentView.frame.height)
26 | isTitleHidden = true
27 | isIconHidden = false
28 | case .text:
29 | titleFrame = CGRect(x: 0, y: 0, width: contentView.frame.width, height: contentView.frame.height)
30 | iconFrame = CGRect(x: 0, y: 0, width: contentView.frame.width, height: contentView.frame.height)
31 | isTitleHidden = false
32 | isIconHidden = true
33 | case .both:
34 | titleFrame = CGRect(x: 0, y: contentView.frame.height*0.75, width: contentView.frame.width, height: contentView.frame.height*0.25)
35 | iconFrame = CGRect(x: 0, y:0, width: contentView.frame.width, height: contentView.frame.height*0.75)
36 | isTitleHidden = false
37 | isIconHidden = false
38 | }
39 |
40 | if toolTitle == nil {
41 | toolTitle = UILabel()
42 | toolTitle?.frame = titleFrame
43 | if let font = font {
44 | toolTitle?.font = font
45 | }
46 | if let color = color {
47 | toolTitle?.textColor = color
48 | }
49 | toolTitle?.textAlignment = .center
50 | contentView.addSubview(toolTitle!)
51 | }
52 |
53 | if toolIcon == nil {
54 | toolIcon = UIImageView()
55 | toolIcon?.frame = iconFrame
56 | toolIcon?.contentMode = .scaleAspectFit
57 | contentView.addSubview(toolIcon!)
58 | }
59 | if let title = toolTitle {
60 | if let txt = text {
61 | title.text = txt
62 | }
63 | title.isHidden = isTitleHidden
64 | }
65 | if let icon = toolIcon {
66 | if let img = image {
67 | icon.image = img
68 | }
69 | icon.isHidden = isIconHidden
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Classes/NotchBar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchBar.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | public class NotchBar: UIView {
11 | /**
12 | This allows you to choose between statusBar & noStatusBar modes.
13 | */
14 | public var mode:notchMode = .statusBar
15 | /**
16 | This allows you to set the height of the NotchBar.
17 | */
18 | public var height:CGFloat = 250
19 | /**
20 | This allows you to set the background color of the NotchBar.
21 | */
22 | public var bgColor:UIColor = .black
23 | /**
24 | This allows you to set the corner radii of the NotchBar.
25 | */
26 | public var curve:CGFloat = 35
27 | /**
28 | This allows you to initially set the NotchBar visibility.
29 | */
30 | public var isVisible:Bool = false
31 | /**
32 | This allows you to set the animation show/hide & rotation animation time interval of the NotchBar.
33 | */
34 | public var animationInterval:TimeInterval = 0.3
35 |
36 | override init(frame: CGRect) {
37 | super.init(frame: frame)
38 | create()
39 | }
40 |
41 | required public init?(coder aDecoder: NSCoder) {
42 | super.init(coder: aDecoder)
43 | create()
44 | }
45 |
46 | var scale:CGFloat!
47 | var multiplier:CGFloat!
48 | func create() {
49 | switch mode {
50 | case .statusBar:
51 | scale = UIScreen.main.portraitNotch.width
52 | multiplier = UIScreen.main.multiplier
53 | case .noStatusBar:
54 | scale = UIScreen.main.widePortraitNotch.width
55 | multiplier = UIScreen.main.multiplierWide
56 | }
57 | self.bounds = CGRect(x: 0, y: 0, width: scale, height: height)
58 | self.center = CGPoint(x: UIScreen.main.portraitNotch.origin.x, y: (self.bounds.height/2))
59 | self.backgroundColor = bgColor
60 | self.draw(.corner, position: .bottom, curve: curve)
61 | self.layer.masksToBounds = true
62 | self.alpha = isVisible ? 1 : 0
63 | }
64 |
65 | /**
66 | This function is used to resize the NotchBar when device orientation is changed.
67 | */
68 | public func refresh(orientation:deviceOrientation) {
69 | let subtrehend = isVisible ? 0 : self.bounds.height
70 |
71 | switch mode {
72 | case .statusBar:
73 | scale = UIScreen.main.portraitNotch.width
74 | multiplier = UIScreen.main.multiplier
75 | case .noStatusBar:
76 | scale = UIScreen.main.widePortraitNotch.width
77 | multiplier = UIScreen.main.multiplierWide
78 | }
79 |
80 | switch orientation {
81 | case .portrait:
82 | UIView.animate(withDuration: animationInterval, animations: {
83 | self.bounds = CGRect(x: 0, y: 0, width: self.scale, height: self.height)
84 | self.center = CGPoint(x: UIScreen.main.portraitNotch.origin.x, y: (self.bounds.height/2) - subtrehend)
85 | self.backgroundColor = self.bgColor
86 | self.draw(.corner, position: .bottom, curve: self.curve)
87 | self.alpha = self.isVisible ? 1 : 0
88 | })
89 | case .landscapeLeft:
90 | UIView.animate(withDuration: animationInterval, animations: {
91 | self.bounds = CGRect(x: 0, y: 0, width: self.height, height: self.scale)
92 | self.center = CGPoint(x: (self.bounds.height*(self.multiplier*self.height)) - subtrehend, y: UIScreen.main.landscapeLeftNotch.origin.y)
93 | self.backgroundColor = self.bgColor
94 | self.draw(.corner, position: .right, curve: self.curve)
95 | self.alpha = self.isVisible ? 1 : 0
96 | })
97 | case .landscapeRight:
98 | UIView.animate(withDuration: animationInterval, animations: {
99 | self.bounds = CGRect(x: 0, y: 0, width: self.height, height: self.scale)
100 | self.center = CGPoint(x: (UIScreen.main.bounds.width-self.bounds.height*(self.multiplier*self.height)) + subtrehend, y: UIScreen.main.landscapeRightNotch.origin.y)
101 | self.backgroundColor = self.bgColor
102 | self.draw(.corner, position: .left, curve: self.curve)
103 | self.alpha = self.isVisible ? 1 : 0
104 | })
105 | }
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Classes/NotchImageView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchImageView.swift
3 | // NotchToolkit
4 | //
5 | // Created by Ahmed Bekhit on 11/1/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | *NotchToolkit* is a framework for iOS that allow developers use the iPhones X notch space in creative ways.
13 |
14 | - Author: Ahmed Fathi Bekhit
15 | * [Github](http://github.com/AFathi)
16 | * [Website](http://ahmedbekhit.com)
17 | * [Twitter](http://twitter.com/iAFapps)
18 | * [Email](mailto:me@ahmedbekhit.com)
19 | */
20 | public class NotchImageView: NotchBar {
21 | // MARK: - Public objects
22 |
23 | /// This delegate is required to detect toolbar actions & automatically resize the NotchBar when device orientation is changed.
24 | public var delegate:NotchToolbarDelegate?
25 |
26 | /// This allows you to enable NotchToolbar only for iPhone X. Default is false.
27 | public var onlyFor10:Bool = false
28 | /// Configure printing bar height
29 | public var printBarHeight:CGFloat = 3
30 | /// Configure printing color
31 | public var printBarColor:UIColor = .cyan
32 | /// Configure image loading duration intervals
33 | public var durationIntervals:TimeInterval = 0.8
34 |
35 | // MARK: - Private Objects
36 | private var recentOrientation: deviceOrientation!
37 | private var imageView:UIImageView = UIImageView()
38 | private var notchImage:UIImage?
39 | private var printerBar:UIView = UIView()
40 | private var isShown:Bool = false
41 | private var isLoaded:Bool = false
42 |
43 | /// Initialize
44 | public init() {
45 | super.init(frame: CGRect.zero)
46 | }
47 | /// Initialize with a UIImage
48 | public init(image: UIImage?) {
49 | super.init(frame: CGRect.zero)
50 | notchImage = image
51 | self.bgColor = .clear
52 | self.animationInterval = 0.1
53 | }
54 |
55 | required public init?(coder aDecoder: NSCoder) {
56 | fatalError("init(coder:) has not been implemented")
57 | }
58 | }
59 |
60 | //MARK:- Methods
61 | extension NotchImageView {
62 | /// This method is required to prepare the NotchImageView in your view controller.
63 | public func prepare(in vc:UIViewController) {
64 | NotificationCenter.default.addObserver(vc, selector: #selector(delegate?.deviceDidRotate), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
65 | if onlyFor10 && !UIScreen.main.isiPhone10 {
66 | print("NotchToolbar: If you want to enable NotchToolBar on this device please add this line to your code\nNotchToolBar().onlyFor10 = false")
67 | }else{
68 | recentOrientation = .portrait
69 | imageView = UIImageView(frame: CGRect(x:0, y:0, width:self.bounds.width, height:self.bounds.height))
70 | imageView.center = CGPoint(x:(self.bounds.width)*0.5, y:-(self.bounds.height*0.5))
71 | imageView.backgroundColor = .clear
72 | imageView.contentMode = .scaleAspectFill
73 | imageView.clipsToBounds = true
74 | imageView.draw(.corner, position: .bottom, curve: self.curve)
75 | if let img = notchImage {
76 | imageView.image = img
77 | }
78 | self.addSubview(imageView)
79 |
80 | printerBar = UIView(frame: CGRect(x:0, y:0, width:self.bounds.width, height:printBarHeight))
81 | printerBar.center = CGPoint(x:self.bounds.width*0.5, y:-(self.bounds.height*0.5))
82 | printerBar.backgroundColor = printBarColor.withAlphaComponent(0.4)
83 | printerBar.layer.shadowColor = printBarColor.cgColor
84 | printerBar.layer.shadowOffset = CGSize(width: 0.0, height: 2.5)
85 | printerBar.layer.shadowOpacity = 1.0
86 | self.addSubview(printerBar)
87 |
88 | vc.view.addSubview(self)
89 | }
90 | }
91 | /// Loads image view from notch with animation
92 | public func load() {
93 | self.isVisible = true
94 |
95 | UIView.animate(withDuration: 0.3, delay: 0.1, usingSpringWithDamping: 1.2, initialSpringVelocity: 0.4, options: [.autoreverse, .repeat], animations: {
96 | self.printerBar.center = CGPoint(x:self.self.bounds.width*0.5, y:(self.self.bounds.height))
97 | })
98 |
99 | autoResize()
100 | isShown = true
101 | updateBounds(orientation: recentOrientation)
102 | }
103 | /// Removes image view from superview
104 | public func remove() {
105 | self.self.removeFromSuperview()
106 | self.removeFromSuperview()
107 | }
108 | /// This function is required to be called from the `deviceDidRotate` delegate function.
109 | public func autoResize() {
110 | switch UIDevice.current.orientation {
111 | case .portrait:
112 | recentOrientation = .portrait
113 | self.refresh(orientation: .portrait)
114 | self.updateBounds(orientation: .portrait)
115 | case .portraitUpsideDown:
116 | self.refresh(orientation: recentOrientation)
117 | self.updateBounds(orientation: recentOrientation)
118 | case .landscapeLeft:
119 | if UIScreen.main.bounds.size.width > UIScreen.main.bounds.height {
120 | recentOrientation = .landscapeLeft
121 | self.refresh(orientation: .landscapeLeft)
122 | self.updateBounds(orientation: .landscapeLeft)
123 | }
124 | case .landscapeRight:
125 | if UIScreen.main.bounds.size.width > UIScreen.main.bounds.height {
126 | recentOrientation = .landscapeRight
127 | self.refresh(orientation: .landscapeRight)
128 | self.updateBounds(orientation: .landscapeRight)
129 | }
130 | case .faceDown:
131 | self.refresh(orientation: recentOrientation)
132 | self.updateBounds(orientation: recentOrientation)
133 | case .faceUp:
134 | self.refresh(orientation: recentOrientation)
135 | self.updateBounds(orientation: recentOrientation)
136 | case .unknown:
137 | self.refresh(orientation: recentOrientation)
138 | self.updateBounds(orientation: recentOrientation)
139 | }
140 | }
141 |
142 | private func updateBounds(orientation: deviceOrientation) {
143 | var xPos = (self.bounds.width*0.5)
144 | var yPos = (self.bounds.height*0.5)
145 | switch orientation {
146 | case .landscapeLeft :
147 | xPos = (!isShown) ? -(self.bounds.width*0.5) : (self.bounds.width*0.5)
148 | case .landscapeRight:
149 | xPos = (!isShown) ? (self.bounds.width*1.5) : (self.bounds.width*0.5)
150 | case .portrait:
151 | yPos = (!isShown) ? -(self.bounds.height*0.5) : (self.bounds.height*0.5)
152 | }
153 |
154 | imageView.bounds = CGRect(x: 0, y: 0, width: self.bounds.size.width, height: self.bounds.size.height)
155 | if self.isLoaded{
156 | self.self.frame = UIScreen.main.bounds
157 | self.imageView.frame = self.self.frame
158 | self.self.draw(.corner, position: .bottom, curve: 0)
159 | self.imageView.draw(.corner, position: .bottom, curve: 0)
160 | return
161 | }
162 |
163 | UIView.animate(withDuration: self.durationIntervals, animations: {
164 | self.imageView.center = CGPoint(x:xPos, y:yPos)
165 | })
166 | if self.isShown {
167 | UIView.animate(withDuration: 0.4, delay: self.durationIntervals, usingSpringWithDamping: 0.4, initialSpringVelocity: 0.4, options: .curveLinear, animations: {
168 | self.self.frame = UIScreen.main.bounds
169 | self.imageView.frame = self.self.frame
170 | self.draw(.corner, position: .bottom, curve: 0)
171 | self.imageView.draw(.corner, position: .bottom, curve: 0)
172 | self.printerBar.alpha = 0
173 | }){ done in
174 | self.isLoaded = true
175 | self.printerBar.layer.removeAllAnimations()
176 | }
177 | }
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Enumerations/CurveSettings.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CurveSettings.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | /**
10 | Types of bezier paths drawn in a view.
11 |
12 | `oval` Is an oval-based bezier path.
13 |
14 | `corner` Is a rounded-rectangle-based bezier path.
15 | */
16 | public enum curveType {
17 | /**
18 | `oval` Is an oval-based bezier path.
19 | */
20 | case oval
21 | /**
22 | `corner` Is a rounded-rectangle-based bezier path.
23 | */
24 | case corner
25 | }
26 |
27 | /**
28 | Position options to draw the bezier paths.
29 |
30 | `right` Draws a bezier path vertically on the right side of a view.
31 | - If **curveType** is `corner`, it draws a rounded rectangle corner on topRight and bottomRight of a view.
32 | - If **curveType** is `oval`, it draws an oval-based bezier path vertically on the right side of a view.
33 |
34 | `left` Draws a bezier path vertically on the left side of a view.
35 | - If **curveType** is `corner`, it draws a rounded rectangle corner on topLeft and bottomLeft of a view.
36 | - If **curveType** is `oval`, it draws an oval-based bezier path vertically on the left side of a view.
37 |
38 | `top` Draws a bezier path horizontally on the top side of a view.
39 | - If **curveType** is `corner`, it draws a rounded rectangle corner on topRight and topLeft of a view.
40 | - If **curveType** is `oval`, it draws an oval-based bezier path horizontally on the top side of a view.
41 |
42 | `bottom` Draws a bezier path vertically on the bottom side of a view.
43 | - If **curveType** is `corner`, it draws a rounded rectangle corner on bottomRight and bottomLeft of a view.
44 | - If **curveType** is `oval`, it draws an oval-based bezier path horizontally on the bottom side of a view.
45 |
46 | `horizontalSides` Draws an oval-based bezier path vertically on the right & left sides of a view.
47 | - Can only be applied when **curveType** is `oval`.
48 |
49 | `verticalSides` Draws an oval-based bezier path horizontally on the top & bottom sides of a view.
50 | - Can only be applied when **curveType** is `oval`.
51 |
52 | `all` Draws a bezier path on all sides of a view.
53 | - If **curveType** is `corner`, it draws rounded rectangle corners in topLeft, topRight, bottomLeft and bottomRight.
54 | - If **curveType** is `oval`, it draws a full oval shape out of the view.
55 | */
56 | public enum curvePosition {
57 | /**
58 | `right` Draws a bezier path vertically on the right side of a view.
59 | */
60 | case right
61 | /**
62 | `left` Draws a bezier path vertically on the left side of a view.
63 | */
64 | case left
65 | /**
66 | `top` Draws a bezier path horizontally on the top side of a view.
67 | */
68 | case top
69 | /**
70 | `bottom` Draws a bezier path vertically on the bottom side of a view.
71 | */
72 | case bottom
73 | /**
74 | `horizontalSides` Draws an oval-based bezier path vertically on the right & left sides of a view.
75 | */
76 | case horizontalSides
77 | /**
78 | `verticalSides` Draws an oval-based bezier path horizontally on the top & bottom sides of a view.
79 | */
80 | case verticalSides
81 | /**
82 | `diagonalAC` Draws rounded rectangle corners diagonally from topLeft to bottomRight of a view.
83 | */
84 | case diagonalAC
85 | /**
86 | `diagonalBD` Draws rounded rectangle corners diagonally from topRight to bottomLeft of a view.
87 | */
88 | case diagonalBD
89 | /**
90 | `all` Draws a bezier path on all sides of a view.
91 | */
92 | case all
93 | }
94 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Enumerations/DeviceOrientation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DeviceOrientation.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | /**
10 | Types of the device orientation used to resize the NotchBar.
11 |
12 | `portrait` When the device's notch is on the top.
13 |
14 | `landscapeLeft` When the device's notch is on the left.
15 |
16 | `landscapeRight` When the device's notch is on the right.
17 |
18 | */
19 | public enum deviceOrientation {
20 | /**
21 | `portrait` When the device's notch is on the top.
22 | */
23 | case portrait
24 | /**
25 | `landscapeLeft` When the device's notch is on the left.
26 | */
27 | case landscapeLeft
28 | /**
29 | `landscapeRight` When the device's notch is on the right.
30 | */
31 | case landscapeRight
32 | }
33 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Enumerations/NotchMode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchMode.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | /**
10 | Modes of the NotchBar based on status bar visibility.
11 | */
12 | public enum notchMode {
13 | /**
14 | This mode sets the width of the NotchBar as the iPhone's X notch width.
15 | */
16 | case statusBar
17 | /**
18 | This mode sets a wider width to display more content. Recommended for full landscape apps and when status bar is hidden.
19 | */
20 | case noStatusBar
21 | }
22 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Enumerations/NotchScroll.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchScroll.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | /**
10 | Types of NotchToolbar scrolling directions.
11 |
12 | `alwaysHorizontal` sets scrolling direction to horizontal with all **deviceOriention** types.
13 |
14 | `alwaysVertical` sets scrolling direction to vertical with all **deviceOriention** types.
15 |
16 | `auto` sets scrolling direction to vertical when **deviceOriention** is `portrait` and horizontal when **deviceOriention** is `landscape`.
17 | */
18 |
19 | public enum notchScroll {
20 | /**
21 | `alwaysHorizontal` sets scrolling direction to horizontal with all **deviceOriention** types.
22 | */
23 | case alwaysHorizontal
24 | /**
25 | `alwaysVertical` sets scrolling direction to vertical with all **deviceOriention** types.
26 | */
27 | case alwaysVertical
28 | /**
29 | `auto` sets scrolling direction to vertical when **deviceOriention** is `portrait` and horizontal when **deviceOriention** is `landscape`.
30 | */
31 | case auto
32 | }
33 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Enumerations/ToolIconTypes.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ToolIconTypes.swift
3 | // NotchToolkit
4 | //
5 | // Created by Ahmed Bekhit on 9/28/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | public enum toolIconTypes {
10 | case image
11 | case text
12 | case both
13 | }
14 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Extenstions/UIScreen+NotchFrame.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIScreen+NotchFrame.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension UIScreen {
12 | private func setNotchFrame(orientation:deviceOrientation, mode:notchMode) -> CGRect {
13 | var notchScale: CGFloat {
14 | switch mode {
15 | case .statusBar:
16 | if self.bounds.size.width > self.bounds.size.height {
17 | return self.bounds.size.height/1.8
18 | }else{
19 | return self.bounds.size.width/1.8
20 | }
21 | case .noStatusBar:
22 | if self.bounds.size.width > self.bounds.size.height {
23 | return self.bounds.size.height/1.5
24 | }else{
25 | return self.bounds.size.width/1.5
26 | }
27 | }
28 | }
29 |
30 | switch orientation {
31 | case .portrait:
32 | return CGRect(x: self.bounds.width/2, y: 0, width: notchScale, height: 0)
33 | case .landscapeLeft:
34 | return CGRect(x: 0, y: self.bounds.height/2, width: 0, height: notchScale)
35 | case .landscapeRight:
36 | return CGRect(x: 0, y: self.bounds.height/2, width: 0, height: notchScale)
37 | }
38 | }
39 |
40 | /**
41 | `portraitNotch` is a rectangle that returns the notch frame when **deviceOrientation** is `portrait`.
42 | */
43 | public var portraitNotch: CGRect {
44 | return setNotchFrame(orientation: .portrait, mode: .statusBar)
45 | }
46 | /**
47 | `landscapeLeftNotch` is a rectangle that returns the notch frame when **deviceOrientation** is `landscapeLeft`.
48 | */
49 | public var landscapeLeftNotch: CGRect {
50 | return setNotchFrame(orientation: .landscapeLeft, mode: .statusBar)
51 | }
52 | /**
53 | `landscapeRightNotch` is a rectangle that returns the notch frame when **deviceOrientation** is `landscapeRight`.
54 | */
55 | public var landscapeRightNotch: CGRect {
56 | return setNotchFrame(orientation: .landscapeRight, mode: .statusBar)
57 | }
58 |
59 | //Wider frame for .noStatusBar mode
60 | /**
61 | `widePortraitNotch` is a rectangle that returns a wider notch frame when **deviceOrientation** is `portrait`.
62 | */
63 | public var widePortraitNotch: CGRect {
64 | return setNotchFrame(orientation: .portrait, mode: .noStatusBar)
65 | }
66 | /**
67 | `wideLandscapeLeftNotch` is a rectangle that returns a wider notch frame when **deviceOrientation** is `landscapeLeft`.
68 | */
69 | public var wideLandscapeLeftNotch: CGRect {
70 | return setNotchFrame(orientation: .landscapeLeft, mode: .noStatusBar)
71 | }
72 | /**
73 | `wideLandscapeRightNotch` is a rectangle that returns a wider notch frame when **deviceOrientation** is `landscapeRight`.
74 | */
75 | public var wideLandscapeRightNotch: CGRect {
76 | return setNotchFrame(orientation: .landscapeRight, mode: .noStatusBar)
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Extenstions/UIScreen+NotchPositionMultiplier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIScreen+NotchPositionMultiplier.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension UIScreen {
12 | private func setMultiplier(mode:notchMode) -> CGFloat {
13 | switch mode {
14 | case .statusBar:
15 | return 0.0021
16 | case .noStatusBar:
17 | return 0.0017
18 | }
19 | }
20 | /**
21 | `multiplier` is a float number that's used to postion the NotchBar when **deviceOrientation** is landscape.
22 | */
23 | public var multiplier: CGFloat {
24 | return setMultiplier(mode: .statusBar)
25 | }
26 | /**
27 | `multiplierWide` is a float number that's used to postion the wide NotchBar when **deviceOrientation** is landscape.
28 | */
29 | public var multiplierWide: CGFloat {
30 | return setMultiplier(mode: .noStatusBar)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Extenstions/UIScreen+iPhone10.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIScreen+iPhone10.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | public extension UIScreen {
11 | /**
12 | `isiPhone10` is a boolean that returns if the device is iPhone X or not.
13 | */
14 | public var isiPhone10: Bool {
15 | return self.nativeBounds.size == CGSize(width: 1125, height: 2436)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Extenstions/UIView+DrawNotch.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+OvalOrCorners.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension UIView {
12 | /**
13 | **UIView.draw(notch type,position,curve,customBounds)** is a UIView extension that allows you add ovals and rounded corners to a UIView.
14 | - For type `oval`, set `curve` from 1.0 - 10.0.
15 | - For type `corner`, `curve` is the radius size.
16 | - Check `curveType` & `curvePosition` for more info.
17 | */
18 | public func draw(_ notch:curveType, position:curvePosition, curve:CGFloat?, customBounds:CGRect? = nil) {
19 | let offset:CGFloat = self.frame.size.width/curve!
20 | var bounds:CGRect!
21 | var viewBounds:CGRect!
22 | var viewPath:UIBezierPath!
23 |
24 | if let finalBounds = customBounds {
25 | bounds = finalBounds
26 | }else{
27 | bounds = self.bounds
28 | }
29 |
30 | switch notch {
31 | case .oval:
32 | var ovalBounds:CGRect!
33 | switch position {
34 | case .right:
35 | ovalBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y - offset / 2, width:bounds.size.width , height:bounds.size.height + offset)
36 | viewBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.size.width/2, height: bounds.size.height)
37 |
38 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
39 | viewPath = UIBezierPath(rect: viewBounds)
40 | viewPath.append(ovalPath)
41 | break
42 | case .left:
43 | ovalBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y - offset / 2, width:bounds.size.width , height:bounds.size.height + offset)
44 | viewBounds = CGRect(x: bounds.origin.x+bounds.size.width/2, y: bounds.origin.y, width: bounds.size.width/2, height: bounds.size.height)
45 |
46 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
47 | viewPath = UIBezierPath(rect: viewBounds)
48 | viewPath.append(ovalPath)
49 | break
50 | case .top:
51 | ovalBounds = CGRect(x: bounds.origin.x - offset / 2, y: bounds.origin.y, width:bounds.size.width + offset, height:bounds.size.height)
52 | viewBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y + bounds.size.height / 2, width: bounds.size.width, height: bounds.size.height / 2)
53 |
54 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
55 | viewPath = UIBezierPath(rect: viewBounds)
56 | viewPath.append(ovalPath)
57 | break
58 | case .bottom:
59 | ovalBounds = CGRect(x: bounds.origin.x - offset / 2, y: bounds.origin.y, width:bounds.size.width + offset, height:bounds.size.height)
60 | viewBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.size.width, height: bounds.size.height / 2)
61 |
62 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
63 | viewPath = UIBezierPath(rect: viewBounds)
64 | viewPath.append(ovalPath)
65 | break
66 | case .horizontalSides:
67 | ovalBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y - offset / 2, width:bounds.size.width , height:bounds.size.height + offset)
68 | viewBounds = CGRect(x: bounds.origin.x+bounds.size.width, y: bounds.origin.y+bounds.size.height, width: bounds.size.width, height: bounds.size.height)
69 |
70 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
71 | viewPath = UIBezierPath(rect: viewBounds)
72 | viewPath.append(ovalPath)
73 | break
74 | case .verticalSides:
75 | ovalBounds = CGRect(x: bounds.origin.x - offset / 2, y: bounds.origin.y, width:bounds.size.width + offset, height:bounds.size.height)
76 | viewBounds = CGRect(x: bounds.origin.x+bounds.size.width, y: bounds.origin.y+bounds.size.height, width: bounds.size.width, height: bounds.size.height)
77 |
78 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
79 | viewPath = UIBezierPath(rect: viewBounds)
80 | viewPath.append(ovalPath)
81 | break
82 | case .all:
83 | viewPath = UIBezierPath(ovalIn: self.bounds)
84 | break
85 | default:
86 | break
87 | }
88 | break
89 | case .corner:
90 | switch position {
91 | case .right:
92 |
93 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topRight, .bottomRight], cornerRadii: CGSize(width:curve!, height:curve!))
94 | break
95 | case .left:
96 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .bottomLeft], cornerRadii: CGSize(width:curve!, height:curve!))
97 | break
98 | case .top:
99 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width:curve!, height:curve!))
100 | break
101 | case .bottom:
102 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width:curve!, height:curve!))
103 | break
104 | case .diagonalAC:
105 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .bottomRight], cornerRadii: CGSize(width:curve!, height:curve!))
106 | break
107 | case .diagonalBD:
108 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topRight, .bottomLeft], cornerRadii: CGSize(width:curve!, height:curve!))
109 | break
110 | case .all:
111 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.allCorners], cornerRadii: CGSize(width:curve!, height:curve!))
112 | break
113 | default:
114 | break
115 | }
116 | break
117 | }
118 | if let path = viewPath {
119 | let shapeLayer: CAShapeLayer = CAShapeLayer()
120 | shapeLayer.frame = bounds
121 | shapeLayer.path = path.cgPath
122 | self.layer.mask = shapeLayer
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.4
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/NotchToolkit.h:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolkit.h
3 | // NotchToolkit
4 | //
5 | // Created by Ahmed Bekhit on 11/6/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for NotchToolkit.
12 | FOUNDATION_EXPORT double NotchToolkitVersionNumber;
13 |
14 | //! Project version string for NotchToolkit.
15 | FOUNDATION_EXPORT const unsigned char NotchToolkitVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Example/NotchToolkit/Protocols/NotchToolbarDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolbarDelegate.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | /**
11 | This delegate is required to detect toolbar actions & automatically resize the NotchBar when device orientation is changed.
12 | */
13 | @objc public protocol NotchToolbarDelegate {
14 | /**
15 | This delegate function detects when the device orientation changes. Calling **autoResize()** function inside this delegate is **required**.
16 | */
17 | func deviceDidRotate()
18 | /**
19 | This delegate function allows you to detect which toolbar icon was selected.
20 | */
21 | func didTapToolIcon(_ tools: UICollectionView, toolIndex:IndexPath, section: Int, row: Int)
22 | }
23 |
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment the next line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | target 'NotchToolkit-Example' do
5 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
6 | use_frameworks!
7 |
8 | # Pods for NotchToolkit-Example
9 | pod 'NotchToolkit', :git => 'https://github.com/AFathi/NotchToolkit.git', :tag => '1.2'
10 |
11 | target 'NotchToolkit-ExampleTests' do
12 | inherit! :search_paths
13 | # Pods for testing
14 | end
15 |
16 | end
17 |
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - NotchToolkit (1.0)
3 |
4 | DEPENDENCIES:
5 | - NotchToolkit (from `https://github.com/AFathi/NotchToolkit.git`, tag `1.0`)
6 |
7 | EXTERNAL SOURCES:
8 | NotchToolkit:
9 | :git: https://github.com/AFathi/NotchToolkit.git
10 | :tag: 1.0
11 |
12 | CHECKOUT OPTIONS:
13 | NotchToolkit:
14 | :git: https://github.com/AFathi/NotchToolkit.git
15 | :tag: 1.0
16 |
17 | SPEC CHECKSUMS:
18 | NotchToolkit: 5aa78dd66d354aad3be2f5e61e8615d2af6b61f6
19 |
20 | PODFILE CHECKSUM: d1eca35aae7b4c7fb911fb7b5985cb76b079dc2a
21 |
22 | COCOAPODS: 1.3.1
23 |
--------------------------------------------------------------------------------
/Example/Pods/Local Podspecs/NotchToolkit.podspec.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "NotchToolkit",
3 | "version": "1.0",
4 | "summary": "A light-weight iOS framework for iPhone's X notch.",
5 | "description": "A light-weight framework for iOS that allow developers use the iPhone's X notch space in creative ways.",
6 | "homepage": "http://github.com/AFathi",
7 | "screenshots": "https://im3.ezgif.com/tmp/ezgif-3-bd73dd3458.gif",
8 | "license": {
9 | "type": "MIT",
10 | "file": "LICENSE"
11 | },
12 | "authors": {
13 | "AFathi": "me@ahmedbekhit.com"
14 | },
15 | "social_media_url": "http://twitter.com/AFathi",
16 | "platforms": {
17 | "ios": "11.0"
18 | },
19 | "source": {
20 | "git": "https://github.com/AFathi/NotchToolkit.git",
21 | "tag": "1.0"
22 | },
23 | "source_files": [
24 | "NotchToolkit",
25 | "NotchToolkit/**/*.{h,m,swift}"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/Example/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - NotchToolkit (1.0)
3 |
4 | DEPENDENCIES:
5 | - NotchToolkit (from `https://github.com/AFathi/NotchToolkit.git`, tag `1.0`)
6 |
7 | EXTERNAL SOURCES:
8 | NotchToolkit:
9 | :git: https://github.com/AFathi/NotchToolkit.git
10 | :tag: 1.0
11 |
12 | CHECKOUT OPTIONS:
13 | NotchToolkit:
14 | :git: https://github.com/AFathi/NotchToolkit.git
15 | :tag: 1.0
16 |
17 | SPEC CHECKSUMS:
18 | NotchToolkit: 5aa78dd66d354aad3be2f5e61e8615d2af6b61f6
19 |
20 | PODFILE CHECKSUM: d1eca35aae7b4c7fb911fb7b5985cb76b079dc2a
21 |
22 | COCOAPODS: 1.3.1
23 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Ahmed Fathi Bekhit[me@ahmedbekhit.com]
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 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/NotchToolkit/Cells/NotchToolCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolCell.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class NotchToolCell: UICollectionViewCell {
12 | private var toolIcon : UIImageView?
13 | private var toolTitle : UILabel?
14 |
15 | func setIcon(_ image:UIImage?) {
16 | if toolIcon == nil {
17 | toolIcon = UIImageView()
18 | toolIcon?.frame = CGRect(x: 0, y:0, width: contentView.frame.width, height: contentView.frame.height)
19 | toolIcon?.contentMode = .scaleAspectFit
20 | contentView.addSubview(toolIcon!)
21 | }
22 |
23 | if let icon = toolIcon {
24 | if let img = image {
25 | icon.image = img
26 | }
27 | icon.isHidden = false
28 | }
29 | if let title = toolTitle {
30 | title.isHidden = true
31 | }
32 | }
33 |
34 | func setTitle(_ text:String, font:UIFont, color:UIColor) {
35 | if toolTitle == nil {
36 | toolTitle = UILabel()
37 | toolTitle?.frame = CGRect(x: 0, y: 0, width: contentView.frame.width, height: contentView.frame.height)
38 | toolTitle?.font = font
39 | toolTitle?.textColor = color
40 | toolTitle?.textAlignment = .center
41 | contentView.addSubview(toolTitle!)
42 | }
43 |
44 | if let title = toolTitle {
45 | title.text = text
46 | title.isHidden = false
47 | }
48 |
49 | if let icon = toolIcon {
50 | icon.isHidden = true
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/NotchToolkit/Enumerators/CurveSettings.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CurveSettings.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | /**
10 | Types of bezier paths drawn in a view.
11 |
12 | `oval` Is an oval-based bezier path.
13 |
14 | `corner` Is a rounded-rectangle-based bezier path.
15 | */
16 | public enum curveType {
17 | /**
18 | `oval` Is an oval-based bezier path.
19 | */
20 | case oval
21 | /**
22 | `corner` Is a rounded-rectangle-based bezier path.
23 | */
24 | case corner
25 | }
26 |
27 | /**
28 | Position options to draw the bezier paths.
29 |
30 | `right` Draws a bezier path vertically on the right side of a view.
31 | - If **curveType** is `corner`, it draws a rounded rectangle corner on topRight and bottomRight of a view.
32 | - If **curveType** is `oval`, it draws an oval-based bezier path vertically on the right side of a view.
33 |
34 | `left` Draws a bezier path vertically on the left side of a view.
35 | - If **curveType** is `corner`, it draws a rounded rectangle corner on topLeft and bottomLeft of a view.
36 | - If **curveType** is `oval`, it draws an oval-based bezier path vertically on the left side of a view.
37 |
38 | `top` Draws a bezier path horizontally on the top side of a view.
39 | - If **curveType** is `corner`, it draws a rounded rectangle corner on topRight and topLeft of a view.
40 | - If **curveType** is `oval`, it draws an oval-based bezier path horizontally on the top side of a view.
41 |
42 | `bottom` Draws a bezier path vertically on the bottom side of a view.
43 | - If **curveType** is `corner`, it draws a rounded rectangle corner on bottomRight and bottomLeft of a view.
44 | - If **curveType** is `oval`, it draws an oval-based bezier path horizontally on the bottom side of a view.
45 |
46 | `horizontalSides` Draws an oval-based bezier path vertically on the right & left sides of a view.
47 | - Can only be applied when **curveType** is `oval`.
48 |
49 | `verticalSides` Draws an oval-based bezier path horizontally on the top & bottom sides of a view.
50 | - Can only be applied when **curveType** is `oval`.
51 |
52 | `all` Draws a bezier path on all sides of a view.
53 | - If **curveType** is `corner`, it draws rounded rectangle corners in topLeft, topRight, bottomLeft and bottomRight.
54 | - If **curveType** is `oval`, it draws a full oval shape out of the view.
55 | */
56 | public enum curvePosition {
57 | /**
58 | `right` Draws a bezier path vertically on the right side of a view.
59 | */
60 | case right
61 | /**
62 | `left` Draws a bezier path vertically on the left side of a view.
63 | */
64 | case left
65 | /**
66 | `top` Draws a bezier path horizontally on the top side of a view.
67 | */
68 | case top
69 | /**
70 | `bottom` Draws a bezier path vertically on the bottom side of a view.
71 | */
72 | case bottom
73 | /**
74 | `horizontalSides` Draws an oval-based bezier path vertically on the right & left sides of a view.
75 | */
76 | case horizontalSides
77 | /**
78 | `verticalSides` Draws an oval-based bezier path horizontally on the top & bottom sides of a view.
79 | */
80 | case verticalSides
81 | /**
82 | `all` Draws a bezier path on all sides of a view.
83 | */
84 | case all
85 | }
86 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/NotchToolkit/Enumerators/DeviceOrientation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DeviceOrientation.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | /**
10 | Types of the device orientation used to resize the NotchBar.
11 |
12 | `portrait` When the device's notch is on the top.
13 |
14 | `landscapeLeft` When the device's notch is on the left.
15 |
16 | `landscapeRight` When the device's notch is on the right.
17 |
18 | */
19 | public enum deviceOrientation {
20 | /**
21 | `portrait` When the device's notch is on the top.
22 | */
23 | case portrait
24 | /**
25 | `landscapeLeft` When the device's notch is on the left.
26 | */
27 | case landscapeLeft
28 | /**
29 | `landscapeRight` When the device's notch is on the right.
30 | */
31 | case landscapeRight
32 | }
33 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/NotchToolkit/Enumerators/NotchMode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchMode.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | /**
10 | Modes of the NotchBar based on status bar visibility.
11 | */
12 | public enum notchMode {
13 | /**
14 | This mode sets the width of the NotchBar as the iPhone's X notch width.
15 | */
16 | case statusBar
17 | /**
18 | This mode sets a wider width to display more content. Recommended for full landscape apps and when status bar is hidden.
19 | */
20 | case noStatusBar
21 | }
22 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/NotchToolkit/Enumerators/NotchScroll.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchScroll.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | /**
10 | Types of NotchToolbar scrolling directions.
11 |
12 | `alwaysHorizontal` sets scrolling direction to horizontal with all **deviceOriention** types.
13 |
14 | `alwaysVertical` sets scrolling direction to vertical with all **deviceOriention** types.
15 |
16 | `auto` sets scrolling direction to vertical when **deviceOriention** is `portrait` and horizontal when **deviceOriention** is `landscape`.
17 | */
18 |
19 | public enum notchScroll {
20 | /**
21 | `alwaysHorizontal` sets scrolling direction to horizontal with all **deviceOriention** types.
22 | */
23 | case alwaysHorizontal
24 | /**
25 | `alwaysVertical` sets scrolling direction to vertical with all **deviceOriention** types.
26 | */
27 | case alwaysVertical
28 | /**
29 | `auto` sets scrolling direction to vertical when **deviceOriention** is `portrait` and horizontal when **deviceOriention** is `landscape`.
30 | */
31 | case auto
32 | }
33 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/NotchToolkit/Extensions/UIScreen+NotchFrame.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIScreen+NotchFrame.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension UIScreen {
12 | private func setNotchFrame(orientation:deviceOrientation, mode:notchMode) -> CGRect {
13 | var notchScale: CGFloat {
14 | switch mode {
15 | case .statusBar:
16 | if self.bounds.size.width > self.bounds.size.height {
17 | return self.bounds.size.height/1.8
18 | }else{
19 | return self.bounds.size.width/1.8
20 | }
21 | case .noStatusBar:
22 | if self.bounds.size.width > self.bounds.size.height {
23 | return self.bounds.size.height/1.5
24 | }else{
25 | return self.bounds.size.width/1.5
26 | }
27 | }
28 | }
29 |
30 | switch orientation {
31 | case .portrait:
32 | return CGRect(x: self.bounds.width/2, y: 0, width: notchScale, height: 0)
33 | case .landscapeLeft:
34 | return CGRect(x: 0, y: self.bounds.height/2, width: 0, height: notchScale)
35 | case .landscapeRight:
36 | return CGRect(x: 0, y: self.bounds.height/2, width: 0, height: notchScale)
37 | }
38 | }
39 |
40 | /**
41 | `portraitNotch` is a rectangle that returns the notch frame when **deviceOrientation** is `portrait`.
42 | */
43 | public var portraitNotch: CGRect {
44 | return setNotchFrame(orientation: .portrait, mode: .statusBar)
45 | }
46 | /**
47 | `landscapeLeftNotch` is a rectangle that returns the notch frame when **deviceOrientation** is `landscapeLeft`.
48 | */
49 | public var landscapeLeftNotch: CGRect {
50 | return setNotchFrame(orientation: .landscapeLeft, mode: .statusBar)
51 | }
52 | /**
53 | `landscapeRightNotch` is a rectangle that returns the notch frame when **deviceOrientation** is `landscapeRight`.
54 | */
55 | public var landscapeRightNotch: CGRect {
56 | return setNotchFrame(orientation: .landscapeRight, mode: .statusBar)
57 | }
58 |
59 | //Wider frame for .noStatusBar mode
60 | /**
61 | `widePortraitNotch` is a rectangle that returns a wider notch frame when **deviceOrientation** is `portrait`.
62 | */
63 | public var widePortraitNotch: CGRect {
64 | return setNotchFrame(orientation: .portrait, mode: .noStatusBar)
65 | }
66 | /**
67 | `wideLandscapeLeftNotch` is a rectangle that returns a wider notch frame when **deviceOrientation** is `landscapeLeft`.
68 | */
69 | public var wideLandscapeLeftNotch: CGRect {
70 | return setNotchFrame(orientation: .landscapeLeft, mode: .noStatusBar)
71 | }
72 | /**
73 | `wideLandscapeRightNotch` is a rectangle that returns a wider notch frame when **deviceOrientation** is `landscapeRight`.
74 | */
75 | public var wideLandscapeRightNotch: CGRect {
76 | return setNotchFrame(orientation: .landscapeRight, mode: .noStatusBar)
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/NotchToolkit/Extensions/UIScreen+NotchPositionMultiplier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIScreen+NotchPositionMultiplier.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension UIScreen {
12 | private func setMultiplier(mode:notchMode) -> CGFloat {
13 | switch mode {
14 | case .statusBar:
15 | return 0.0021
16 | case .noStatusBar:
17 | return 0.0017
18 | }
19 | }
20 | /**
21 | `multiplier` is a float number that's used to postion the NotchBar when **deviceOrientation** is landscape.
22 | */
23 | public var multiplier: CGFloat {
24 | return setMultiplier(mode: .statusBar)
25 | }
26 | /**
27 | `multiplierWide` is a float number that's used to postion the wide NotchBar when **deviceOrientation** is landscape.
28 | */
29 | public var multiplierWide: CGFloat {
30 | return setMultiplier(mode: .noStatusBar)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/NotchToolkit/Extensions/UIScreen+iPhone10.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIScreen+iPhone10.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | public extension UIScreen {
11 | /**
12 | `isiPhone10` is a boolean that returns if the device is iPhone X or not.
13 | */
14 | public var isiPhone10: Bool {
15 | return self.nativeBounds.size == CGSize(width: 1125, height: 2436)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/NotchToolkit/Extensions/UIView+OvalOrCorners.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+OvalOrCorners.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension UIView {
12 | /**
13 | **UIView.addOvalOrCorner(type,position,curve,customBounds)** is a UIView extension that allows you add ovals and rounded corners to a UIView.
14 | - For type `oval`, set `curve` from 1.0 - 10.0.
15 | - For type `corner`, `curve` is the radius size.
16 | - Check `curveType` & `curvePosition` for more info.
17 | */
18 | public func addOvalOrCorner(type:curveType, position:curvePosition, curve:CGFloat?, customBounds:CGRect? = nil) {
19 | let offset:CGFloat = self.frame.size.width/curve!
20 | var bounds:CGRect!
21 | var viewBounds:CGRect!
22 | var viewPath:UIBezierPath!
23 |
24 | if let finalBounds = customBounds {
25 | bounds = finalBounds
26 | }else{
27 | bounds = self.bounds
28 | }
29 |
30 | switch type {
31 | case .oval:
32 | var ovalBounds:CGRect!
33 | switch position {
34 | case .right:
35 | ovalBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y - offset / 2, width:bounds.size.width , height:bounds.size.height + offset)
36 | viewBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.size.width/2, height: bounds.size.height)
37 |
38 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
39 | viewPath = UIBezierPath(rect: viewBounds)
40 | viewPath.append(ovalPath)
41 | break
42 | case .left:
43 | ovalBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y - offset / 2, width:bounds.size.width , height:bounds.size.height + offset)
44 | viewBounds = CGRect(x: bounds.origin.x+bounds.size.width/2, y: bounds.origin.y, width: bounds.size.width/2, height: bounds.size.height)
45 |
46 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
47 | viewPath = UIBezierPath(rect: viewBounds)
48 | viewPath.append(ovalPath)
49 | break
50 | case .top:
51 | ovalBounds = CGRect(x: bounds.origin.x - offset / 2, y: bounds.origin.y, width:bounds.size.width + offset, height:bounds.size.height)
52 | viewBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y + bounds.size.height / 2, width: bounds.size.width, height: bounds.size.height / 2)
53 |
54 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
55 | viewPath = UIBezierPath(rect: viewBounds)
56 | viewPath.append(ovalPath)
57 | break
58 | case .bottom:
59 | ovalBounds = CGRect(x: bounds.origin.x - offset / 2, y: bounds.origin.y, width:bounds.size.width + offset, height:bounds.size.height)
60 | viewBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.size.width, height: bounds.size.height / 2)
61 |
62 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
63 | viewPath = UIBezierPath(rect: viewBounds)
64 | viewPath.append(ovalPath)
65 | break
66 | case .horizontalSides:
67 | ovalBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y - offset / 2, width:bounds.size.width , height:bounds.size.height + offset)
68 | viewBounds = CGRect(x: bounds.origin.x+bounds.size.width, y: bounds.origin.y+bounds.size.height, width: bounds.size.width, height: bounds.size.height)
69 |
70 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
71 | viewPath = UIBezierPath(rect: viewBounds)
72 | viewPath.append(ovalPath)
73 | break
74 | case .verticalSides:
75 | ovalBounds = CGRect(x: bounds.origin.x - offset / 2, y: bounds.origin.y, width:bounds.size.width + offset, height:bounds.size.height)
76 | viewBounds = CGRect(x: bounds.origin.x+bounds.size.width, y: bounds.origin.y+bounds.size.height, width: bounds.size.width, height: bounds.size.height)
77 |
78 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
79 | viewPath = UIBezierPath(rect: viewBounds)
80 | viewPath.append(ovalPath)
81 | break
82 | case .all:
83 | viewPath = UIBezierPath(ovalIn: self.bounds)
84 | break
85 | }
86 | break
87 | case .corner:
88 | switch position {
89 | case .right:
90 |
91 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topRight, .bottomRight], cornerRadii: CGSize(width:curve!, height:curve!))
92 | break
93 | case .left:
94 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .bottomLeft], cornerRadii: CGSize(width:curve!, height:curve!))
95 | break
96 | case .top:
97 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width:curve!, height:curve!))
98 | break
99 | case .bottom:
100 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width:curve!, height:curve!))
101 | break
102 | case .all:
103 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.allCorners], cornerRadii: CGSize(width:curve!, height:curve!))
104 | break
105 | default:
106 | break
107 | }
108 | break
109 | }
110 | if let path = viewPath {
111 | let shapeLayer: CAShapeLayer = CAShapeLayer()
112 | shapeLayer.frame = bounds
113 | shapeLayer.path = path.cgPath
114 | self.layer.mask = shapeLayer
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/NotchToolkit/NotchBar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchBar.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | public class NotchBar: UIView {
11 | /**
12 | This allows you to choose between statusBar & noStatusBar modes.
13 | */
14 | public var mode:notchMode = .statusBar
15 | /**
16 | This allows you to set the height of the NotchBar.
17 | */
18 | public var height:CGFloat = 250
19 | /**
20 | This allows you to set the background color of the NotchBar.
21 | */
22 | public var bgColor:UIColor = .black
23 | /**
24 | This allows you to set the corner radii of the NotchBar.
25 | */
26 | public var curve:CGFloat = 35
27 | /**
28 | This allows you to initially set the NotchBar visibility.
29 | */
30 | public var isVisible:Bool = false
31 | /**
32 | This allows you to set the animation show/hide & rotation animation time interval of the NotchBar.
33 | */
34 | public var animationInterval:TimeInterval = 0.3
35 |
36 | override init(frame: CGRect) {
37 | super.init(frame: frame)
38 | create()
39 | }
40 |
41 | required public init?(coder aDecoder: NSCoder) {
42 | super.init(coder: aDecoder)
43 | create()
44 | }
45 |
46 | var scale:CGFloat!
47 | var multiplier:CGFloat!
48 | func create() {
49 | switch mode {
50 | case .statusBar:
51 | scale = UIScreen.main.portraitNotch.width
52 | multiplier = UIScreen.main.multiplier
53 | case .noStatusBar:
54 | scale = UIScreen.main.widePortraitNotch.width
55 | multiplier = UIScreen.main.multiplierWide
56 | }
57 | self.bounds = CGRect(x: 0, y: 0, width: scale, height: height)
58 | self.center = CGPoint(x: UIScreen.main.portraitNotch.origin.x, y: (self.bounds.height/2))
59 | self.backgroundColor = bgColor
60 | self.addOvalOrCorner(type: .corner, position: .bottom, curve: curve)
61 | self.layer.masksToBounds = true
62 | self.alpha = isVisible ? 1 : 0
63 | }
64 |
65 | /**
66 | This function is used to resize the NotchBar when device orientation is changed.
67 | */
68 | public func refresh(orientation:deviceOrientation) {
69 | let subtrehend = isVisible ? 0 : self.bounds.height
70 |
71 | switch mode {
72 | case .statusBar:
73 | scale = UIScreen.main.portraitNotch.width
74 | multiplier = UIScreen.main.multiplier
75 | case .noStatusBar:
76 | scale = UIScreen.main.widePortraitNotch.width
77 | multiplier = UIScreen.main.multiplierWide
78 | }
79 |
80 | switch orientation {
81 | case .portrait:
82 | UIView.animate(withDuration: animationInterval, animations: {
83 | self.bounds = CGRect(x: 0, y: 0, width: self.scale, height: self.height)
84 | self.center = CGPoint(x: UIScreen.main.portraitNotch.origin.x, y: (self.bounds.height/2) - subtrehend)
85 | self.backgroundColor = self.bgColor
86 | self.addOvalOrCorner(type: .corner, position: .bottom, curve: self.curve)
87 | self.alpha = self.isVisible ? 1 : 0
88 | })
89 | case .landscapeLeft:
90 | UIView.animate(withDuration: animationInterval, animations: {
91 | self.bounds = CGRect(x: 0, y: 0, width: self.height, height: self.scale)
92 | self.center = CGPoint(x: (self.bounds.height*(self.multiplier*self.height)) - subtrehend, y: UIScreen.main.landscapeLeftNotch.origin.y)
93 | self.backgroundColor = self.bgColor
94 | self.addOvalOrCorner(type: .corner, position: .right, curve: self.curve)
95 | self.alpha = self.isVisible ? 1 : 0
96 | })
97 | case .landscapeRight:
98 | UIView.animate(withDuration: animationInterval, animations: {
99 | self.bounds = CGRect(x: 0, y: 0, width: self.height, height: self.scale)
100 | self.center = CGPoint(x: (UIScreen.main.bounds.width-self.bounds.height*(self.multiplier*self.height)) + subtrehend, y: UIScreen.main.landscapeRightNotch.origin.y)
101 | self.backgroundColor = self.bgColor
102 | self.addOvalOrCorner(type: .corner, position: .left, curve: self.curve)
103 | self.alpha = self.isVisible ? 1 : 0
104 | })
105 | }
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/NotchToolkit/NotchToolbar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolbar.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | *NotchToolkit* is a light-weight framework for iOS that allow developers use the iPhone's X notch space in creative ways.
13 |
14 | - Author: Ahmed Fathi Bekhit
15 | * [Github](http://github.com/AFathi)
16 | * [Website](http://ahmedbekhit.com)
17 | * [Twitter](http://twitter.com/iAFapps)
18 | * [Email](mailto:me@ahmedbekhit.com)
19 | */
20 | public class NotchToolbar: NSObject, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate {
21 | /**
22 | This delegate is required to detect toolbar actions & automatically resize the NotchBar when device orientation is changed.
23 | */
24 | public var delegate:NotchToolbarDelegate?
25 | /**
26 | This provides you options to customize NotchBar.
27 | */
28 | public var notch:NotchBar = NotchBar()
29 | /**
30 | This gives you options to change the NotchToolbar scrolling directions. Default is auto.
31 | */
32 | public var scrollMode:notchScroll = .auto
33 |
34 | /**
35 | This allows you to enable NotchToolbar only for iPhone X. Default is false.
36 | */
37 | public var onlyFor10:Bool = false
38 | /**
39 | This is the collection view that loads the toolList.
40 | */
41 | public var tools:UICollectionView?
42 | /**
43 | This allows you to set the tool icon size. Default is 60x60
44 | */
45 | public var toolIconSize:CGSize = CGSize(width: 60, height: 60)
46 | /**
47 | This allows you to customize the collection view edge insets.
48 | */
49 | public var toolIconsInsets:UIEdgeInsets = UIEdgeInsetsMake(5, 35, 5, 35)
50 | /**
51 | This is the array of the tool icons in the NotchToolbar. You may only use String & UIImage types.
52 | */
53 | public var toolList:[Any?] = ["🤓", "😊", "🙄", "👩🔬", "👨💻"]
54 | /**
55 | This allows you to customize the tools title font.
56 | */
57 | public var toolsTitleFont:UIFont = UIFont(name:"Avenir-Medium", size: 45)!
58 | /**
59 | This allows you to customize the tools title color.
60 | */
61 | public var toolsTitleColor:UIColor = .white
62 |
63 | public var toolsFlow = UICollectionViewFlowLayout()
64 |
65 | /**
66 | This function is required to initialize the NotchToolbar.
67 | */
68 | public func prepare(in vc:UIViewController) {
69 | NotificationCenter.default.addObserver(vc, selector: #selector(delegate?.deviceDidRotate), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
70 | if onlyFor10 && !UIScreen.main.isiPhone10 {
71 | print("NotchToolbar: If you want to enable NotchToolBar on this device please add this line to your code\nNotchToolBar().onlyFor10 = false")
72 | }else{
73 | switch scrollMode {
74 | case .alwaysHorizontal:
75 | toolsFlow.scrollDirection = .horizontal
76 | case .alwaysVertical:
77 | toolsFlow.scrollDirection = .vertical
78 | default:
79 | break
80 | }
81 | tools = UICollectionView(frame: CGRect(x:0, y:0, width:notch.bounds.width, height:notch.bounds.height), collectionViewLayout: toolsFlow)
82 | tools?.register(NotchToolCell.self, forCellWithReuseIdentifier: "toolCell")
83 | tools?.delegate = self
84 | tools?.dataSource = self
85 | tools?.contentOffset = CGPoint(x: 0, y: 0)
86 | tools?.backgroundColor = .clear
87 | tools?.setContentOffset(CGPoint.zero, animated: false)
88 | notch.addSubview(tools!)
89 | vc.view.addSubview(notch)
90 | }
91 | }
92 |
93 | /**
94 | This function allows you to show and hide the NotchToolbar.
95 | */
96 | public func showOrHide() {
97 | notch.isVisible = notch.isVisible ? false : true
98 | autoResize()
99 | }
100 | }
101 |
102 | //MARK:- NotchToolbarDelegates
103 | extension NotchToolbar {
104 | /**
105 | This function is required to be called from the `deviceDidRotate` delegate function.
106 | */
107 | public func autoResize() {
108 | var offsetPoint:CGPoint! = CGPoint.zero
109 | if UIScreen.main.bounds.size.width > UIScreen.main.bounds.height {
110 | switch scrollMode {
111 | case .auto:
112 | offsetPoint = CGPoint(x:-(pow(toolIconsInsets.top, 2.4)),y:0)
113 | toolsFlow.scrollDirection = .horizontal
114 | case .alwaysVertical:
115 | offsetPoint = CGPoint(x:-(pow(toolIconsInsets.top, 2.4)),y:0)
116 | default:
117 | break
118 | }
119 | }else{
120 | switch scrollMode {
121 | case .auto:
122 | offsetPoint = CGPoint(x:0,y:-(pow(toolIconsInsets.top, 2.4)))
123 | toolsFlow.scrollDirection = .vertical
124 | case .alwaysVertical:
125 | offsetPoint = CGPoint(x:0,y:-(pow(toolIconsInsets.top, 2.4)))
126 | default:
127 | break
128 | }
129 | }
130 |
131 | switch UIDevice.current.orientation {
132 | case .portrait:
133 | notch.refresh(orientation: .portrait)
134 | tools?.bounds = CGRect(x: 0, y: 0, width: notch.bounds.size.width, height: notch.bounds.size.height)
135 | tools?.center = CGPoint(x: notch.bounds.size.width/2, y: notch.bounds.size.height/2)
136 | tools?.reloadData()
137 | tools?.setContentOffset(offsetPoint, animated: false)
138 | case .portraitUpsideDown:
139 | //no changes
140 | break
141 | case .landscapeLeft:
142 | if UIScreen.main.bounds.size.width > UIScreen.main.bounds.height {
143 | notch.refresh(orientation: .landscapeLeft)
144 | tools?.bounds = CGRect(x: 0, y: 0, width: notch.bounds.size.width, height: notch.bounds.size.height)
145 | tools?.center = CGPoint(x: notch.bounds.size.width/2, y: notch.bounds.size.height/2)
146 | tools?.reloadData()
147 | tools?.setContentOffset(offsetPoint, animated: false)
148 | }
149 | case .landscapeRight:
150 | if UIScreen.main.bounds.size.width > UIScreen.main.bounds.height {
151 | notch.refresh(orientation: .landscapeRight)
152 | tools?.bounds = CGRect(x: 0, y: 0, width: notch.bounds.size.width, height: notch.bounds.size.height)
153 | tools?.center = CGPoint(x: notch.bounds.size.width/2, y: notch.bounds.size.height/2)
154 | tools?.reloadData()
155 | tools?.setContentOffset(offsetPoint, animated: false)
156 | }
157 | default:
158 | break
159 | }
160 | }
161 |
162 | public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
163 | return toolList.count
164 | }
165 |
166 | public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
167 | let cell:NotchToolCell = collectionView.dequeueReusableCell(withReuseIdentifier: "toolCell", for: indexPath as IndexPath) as! NotchToolCell
168 | if let text = toolList[indexPath.row] as? String {
169 | cell.setTitle(text, font: toolsTitleFont, color: toolsTitleColor)
170 | }else if let image = toolList[indexPath.row] as? UIImage {
171 | cell.setIcon(image)
172 | }
173 |
174 | return cell
175 | }
176 |
177 | public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
178 | return toolIconSize
179 | }
180 |
181 | public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
182 | delegate?.didTapToolIcon(collectionView, toolIndex: indexPath, section: indexPath.section, row: indexPath.row)
183 | }
184 |
185 | public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
186 | return toolIconsInsets
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/NotchToolkit/NotchToolkit.h:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolkit.h
3 | // NotchToolkit
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for NotchToolkit.
12 | FOUNDATION_EXPORT double NotchToolkitVersionNumber;
13 |
14 | //! Project version string for NotchToolkit.
15 | FOUNDATION_EXPORT const unsigned char NotchToolkitVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/NotchToolkit/Protocols/NotchToolbarDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolbarDelegate.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | /**
11 | This delegate is required to detect toolbar actions & automatically resize the NotchBar when device orientation is changed.
12 | */
13 | @objc public protocol NotchToolbarDelegate {
14 | /**
15 | This delegate function detects when the device orientation changes. Calling **autoResize()** function inside this delegate is **required**.
16 | */
17 | func deviceDidRotate()
18 | /**
19 | This delegate function allows you to detect which toolbar icon was selected.
20 | */
21 | func didTapToolIcon(_ tools: UICollectionView, toolIndex:IndexPath, section: Int, row: Int)
22 | }
23 |
--------------------------------------------------------------------------------
/Example/Pods/NotchToolkit/README.md:
--------------------------------------------------------------------------------
1 | # NotchToolkit
2 | NotchToolkit is a light-weight framework for iOS that allow developers use the iPhone's X notch space in creative ways
3 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/NotchToolkit/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 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/NotchToolkit/NotchToolkit-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_NotchToolkit : NSObject
3 | @end
4 | @implementation PodsDummy_NotchToolkit
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/NotchToolkit/NotchToolkit-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/NotchToolkit/NotchToolkit-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 | #import "NotchToolkit.h"
14 |
15 | FOUNDATION_EXPORT double NotchToolkitVersionNumber;
16 | FOUNDATION_EXPORT const unsigned char NotchToolkitVersionString[];
17 |
18 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/NotchToolkit/NotchToolkit.modulemap:
--------------------------------------------------------------------------------
1 | framework module NotchToolkit {
2 | umbrella header "NotchToolkit-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/NotchToolkit/NotchToolkit.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/NotchToolkit
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
5 | PODS_BUILD_DIR = $BUILD_DIR
6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_ROOT = ${SRCROOT}
8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/NotchToolkit
9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
10 | SKIP_INSTALL = YES
11 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-Example/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 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-Example/Pods-NotchToolkit-Example-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## NotchToolkit
5 |
6 | MIT License
7 |
8 | Copyright (c) 2017 Ahmed Fathi Bekhit[me@ahmedbekhit.com]
9 |
10 | Permission is hereby granted, free of charge, to any person obtaining a copy
11 | of this software and associated documentation files (the "Software"), to deal
12 | in the Software without restriction, including without limitation the rights
13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | copies of the Software, and to permit persons to whom the Software is
15 | furnished to do so, subject to the following conditions:
16 |
17 | The above copyright notice and this permission notice shall be included in all
18 | copies or substantial portions of the Software.
19 |
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | SOFTWARE.
27 |
28 | Generated by CocoaPods - https://cocoapods.org
29 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-Example/Pods-NotchToolkit-Example-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | MIT License
18 |
19 | Copyright (c) 2017 Ahmed Fathi Bekhit[me@ahmedbekhit.com]
20 |
21 | Permission is hereby granted, free of charge, to any person obtaining a copy
22 | of this software and associated documentation files (the "Software"), to deal
23 | in the Software without restriction, including without limitation the rights
24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 | copies of the Software, and to permit persons to whom the Software is
26 | furnished to do so, subject to the following conditions:
27 |
28 | The above copyright notice and this permission notice shall be included in all
29 | copies or substantial portions of the Software.
30 |
31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37 | SOFTWARE.
38 |
39 | License
40 | MIT
41 | Title
42 | NotchToolkit
43 | Type
44 | PSGroupSpecifier
45 |
46 |
47 | FooterText
48 | Generated by CocoaPods - https://cocoapods.org
49 | Title
50 |
51 | Type
52 | PSGroupSpecifier
53 |
54 |
55 | StringsTable
56 | Acknowledgements
57 | Title
58 | Acknowledgements
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-Example/Pods-NotchToolkit-Example-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_NotchToolkit_Example : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_NotchToolkit_Example
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-Example/Pods-NotchToolkit-Example-frameworks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
6 |
7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
8 |
9 | # This protects against multiple targets copying the same framework dependency at the same time. The solution
10 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
11 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
12 |
13 | install_framework()
14 | {
15 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
16 | local source="${BUILT_PRODUCTS_DIR}/$1"
17 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
18 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
19 | elif [ -r "$1" ]; then
20 | local source="$1"
21 | fi
22 |
23 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
24 |
25 | if [ -L "${source}" ]; then
26 | echo "Symlinked..."
27 | source="$(readlink "${source}")"
28 | fi
29 |
30 | # Use filter instead of exclude so missing patterns don't throw errors.
31 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
32 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
33 |
34 | local basename
35 | basename="$(basename -s .framework "$1")"
36 | binary="${destination}/${basename}.framework/${basename}"
37 | if ! [ -r "$binary" ]; then
38 | binary="${destination}/${basename}"
39 | fi
40 |
41 | # Strip invalid architectures so "fat" simulator / device frameworks work on device
42 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
43 | strip_invalid_archs "$binary"
44 | fi
45 |
46 | # Resign the code if required by the build settings to avoid unstable apps
47 | code_sign_if_enabled "${destination}/$(basename "$1")"
48 |
49 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
50 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
51 | local swift_runtime_libs
52 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
53 | for lib in $swift_runtime_libs; do
54 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
55 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
56 | code_sign_if_enabled "${destination}/${lib}"
57 | done
58 | fi
59 | }
60 |
61 | # Copies the dSYM of a vendored framework
62 | install_dsym() {
63 | local source="$1"
64 | if [ -r "$source" ]; then
65 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\""
66 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}"
67 | fi
68 | }
69 |
70 | # Signs a framework with the provided identity
71 | code_sign_if_enabled() {
72 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
73 | # Use the current code_sign_identitiy
74 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
75 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'"
76 |
77 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
78 | code_sign_cmd="$code_sign_cmd &"
79 | fi
80 | echo "$code_sign_cmd"
81 | eval "$code_sign_cmd"
82 | fi
83 | }
84 |
85 | # Strip invalid architectures
86 | strip_invalid_archs() {
87 | binary="$1"
88 | # Get architectures for current file
89 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
90 | stripped=""
91 | for arch in $archs; do
92 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then
93 | # Strip non-valid architectures in-place
94 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1
95 | stripped="$stripped $arch"
96 | fi
97 | done
98 | if [[ "$stripped" ]]; then
99 | echo "Stripped $binary of architectures:$stripped"
100 | fi
101 | }
102 |
103 |
104 | if [[ "$CONFIGURATION" == "Debug" ]]; then
105 | install_framework "${BUILT_PRODUCTS_DIR}/NotchToolkit/NotchToolkit.framework"
106 | fi
107 | if [[ "$CONFIGURATION" == "Release" ]]; then
108 | install_framework "${BUILT_PRODUCTS_DIR}/NotchToolkit/NotchToolkit.framework"
109 | fi
110 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
111 | wait
112 | fi
113 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-Example/Pods-NotchToolkit-Example-resources.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
5 |
6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
7 | > "$RESOURCES_TO_COPY"
8 |
9 | XCASSET_FILES=()
10 |
11 | # This protects against multiple targets copying the same framework dependency at the same time. The solution
12 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
13 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
14 |
15 | case "${TARGETED_DEVICE_FAMILY}" in
16 | 1,2)
17 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
18 | ;;
19 | 1)
20 | TARGET_DEVICE_ARGS="--target-device iphone"
21 | ;;
22 | 2)
23 | TARGET_DEVICE_ARGS="--target-device ipad"
24 | ;;
25 | 3)
26 | TARGET_DEVICE_ARGS="--target-device tv"
27 | ;;
28 | 4)
29 | TARGET_DEVICE_ARGS="--target-device watch"
30 | ;;
31 | *)
32 | TARGET_DEVICE_ARGS="--target-device mac"
33 | ;;
34 | esac
35 |
36 | install_resource()
37 | {
38 | if [[ "$1" = /* ]] ; then
39 | RESOURCE_PATH="$1"
40 | else
41 | RESOURCE_PATH="${PODS_ROOT}/$1"
42 | fi
43 | if [[ ! -e "$RESOURCE_PATH" ]] ; then
44 | cat << EOM
45 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
46 | EOM
47 | exit 1
48 | fi
49 | case $RESOURCE_PATH in
50 | *.storyboard)
51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
53 | ;;
54 | *.xib)
55 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
56 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
57 | ;;
58 | *.framework)
59 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
60 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
61 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
62 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
63 | ;;
64 | *.xcdatamodel)
65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true
66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
67 | ;;
68 | *.xcdatamodeld)
69 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true
70 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
71 | ;;
72 | *.xcmappingmodel)
73 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true
74 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
75 | ;;
76 | *.xcassets)
77 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
78 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
79 | ;;
80 | *)
81 | echo "$RESOURCE_PATH" || true
82 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
83 | ;;
84 | esac
85 | }
86 |
87 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
88 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
89 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
90 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
91 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
92 | fi
93 | rm -f "$RESOURCES_TO_COPY"
94 |
95 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
96 | then
97 | # Find all other xcassets (this unfortunately includes those of path pods and other targets).
98 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
99 | while read line; do
100 | if [[ $line != "${PODS_ROOT}*" ]]; then
101 | XCASSET_FILES+=("$line")
102 | fi
103 | done <<<"$OTHER_XCASSETS"
104 |
105 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
106 | fi
107 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-Example/Pods-NotchToolkit-Example-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_NotchToolkit_ExampleVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_NotchToolkit_ExampleVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-Example/Pods-NotchToolkit-Example.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/NotchToolkit"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/NotchToolkit/NotchToolkit.framework/Headers"
6 | OTHER_LDFLAGS = $(inherited) -framework "NotchToolkit"
7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
8 | PODS_BUILD_DIR = $BUILD_DIR
9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
11 | PODS_ROOT = ${SRCROOT}/Pods
12 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-Example/Pods-NotchToolkit-Example.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_NotchToolkit_Example {
2 | umbrella header "Pods-NotchToolkit-Example-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-Example/Pods-NotchToolkit-Example.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/NotchToolkit"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/NotchToolkit/NotchToolkit.framework/Headers"
6 | OTHER_LDFLAGS = $(inherited) -framework "NotchToolkit"
7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
8 | PODS_BUILD_DIR = $BUILD_DIR
9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
11 | PODS_ROOT = ${SRCROOT}/Pods
12 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-ExampleTests/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 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-ExampleTests/Pods-NotchToolkit-ExampleTests-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 | Generated by CocoaPods - https://cocoapods.org
4 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-ExampleTests/Pods-NotchToolkit-ExampleTests-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | Generated by CocoaPods - https://cocoapods.org
18 | Title
19 |
20 | Type
21 | PSGroupSpecifier
22 |
23 |
24 | StringsTable
25 | Acknowledgements
26 | Title
27 | Acknowledgements
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-ExampleTests/Pods-NotchToolkit-ExampleTests-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_NotchToolkit_ExampleTests : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_NotchToolkit_ExampleTests
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-ExampleTests/Pods-NotchToolkit-ExampleTests-frameworks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
6 |
7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
8 |
9 | # This protects against multiple targets copying the same framework dependency at the same time. The solution
10 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
11 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
12 |
13 | install_framework()
14 | {
15 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
16 | local source="${BUILT_PRODUCTS_DIR}/$1"
17 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
18 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
19 | elif [ -r "$1" ]; then
20 | local source="$1"
21 | fi
22 |
23 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
24 |
25 | if [ -L "${source}" ]; then
26 | echo "Symlinked..."
27 | source="$(readlink "${source}")"
28 | fi
29 |
30 | # Use filter instead of exclude so missing patterns don't throw errors.
31 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
32 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
33 |
34 | local basename
35 | basename="$(basename -s .framework "$1")"
36 | binary="${destination}/${basename}.framework/${basename}"
37 | if ! [ -r "$binary" ]; then
38 | binary="${destination}/${basename}"
39 | fi
40 |
41 | # Strip invalid architectures so "fat" simulator / device frameworks work on device
42 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
43 | strip_invalid_archs "$binary"
44 | fi
45 |
46 | # Resign the code if required by the build settings to avoid unstable apps
47 | code_sign_if_enabled "${destination}/$(basename "$1")"
48 |
49 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
50 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
51 | local swift_runtime_libs
52 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
53 | for lib in $swift_runtime_libs; do
54 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
55 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
56 | code_sign_if_enabled "${destination}/${lib}"
57 | done
58 | fi
59 | }
60 |
61 | # Copies the dSYM of a vendored framework
62 | install_dsym() {
63 | local source="$1"
64 | if [ -r "$source" ]; then
65 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\""
66 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}"
67 | fi
68 | }
69 |
70 | # Signs a framework with the provided identity
71 | code_sign_if_enabled() {
72 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
73 | # Use the current code_sign_identitiy
74 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
75 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'"
76 |
77 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
78 | code_sign_cmd="$code_sign_cmd &"
79 | fi
80 | echo "$code_sign_cmd"
81 | eval "$code_sign_cmd"
82 | fi
83 | }
84 |
85 | # Strip invalid architectures
86 | strip_invalid_archs() {
87 | binary="$1"
88 | # Get architectures for current file
89 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
90 | stripped=""
91 | for arch in $archs; do
92 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then
93 | # Strip non-valid architectures in-place
94 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1
95 | stripped="$stripped $arch"
96 | fi
97 | done
98 | if [[ "$stripped" ]]; then
99 | echo "Stripped $binary of architectures:$stripped"
100 | fi
101 | }
102 |
103 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
104 | wait
105 | fi
106 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-ExampleTests/Pods-NotchToolkit-ExampleTests-resources.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
5 |
6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
7 | > "$RESOURCES_TO_COPY"
8 |
9 | XCASSET_FILES=()
10 |
11 | # This protects against multiple targets copying the same framework dependency at the same time. The solution
12 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
13 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
14 |
15 | case "${TARGETED_DEVICE_FAMILY}" in
16 | 1,2)
17 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
18 | ;;
19 | 1)
20 | TARGET_DEVICE_ARGS="--target-device iphone"
21 | ;;
22 | 2)
23 | TARGET_DEVICE_ARGS="--target-device ipad"
24 | ;;
25 | 3)
26 | TARGET_DEVICE_ARGS="--target-device tv"
27 | ;;
28 | 4)
29 | TARGET_DEVICE_ARGS="--target-device watch"
30 | ;;
31 | *)
32 | TARGET_DEVICE_ARGS="--target-device mac"
33 | ;;
34 | esac
35 |
36 | install_resource()
37 | {
38 | if [[ "$1" = /* ]] ; then
39 | RESOURCE_PATH="$1"
40 | else
41 | RESOURCE_PATH="${PODS_ROOT}/$1"
42 | fi
43 | if [[ ! -e "$RESOURCE_PATH" ]] ; then
44 | cat << EOM
45 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
46 | EOM
47 | exit 1
48 | fi
49 | case $RESOURCE_PATH in
50 | *.storyboard)
51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
53 | ;;
54 | *.xib)
55 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
56 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
57 | ;;
58 | *.framework)
59 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
60 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
61 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
62 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
63 | ;;
64 | *.xcdatamodel)
65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true
66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
67 | ;;
68 | *.xcdatamodeld)
69 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true
70 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
71 | ;;
72 | *.xcmappingmodel)
73 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true
74 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
75 | ;;
76 | *.xcassets)
77 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
78 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
79 | ;;
80 | *)
81 | echo "$RESOURCE_PATH" || true
82 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
83 | ;;
84 | esac
85 | }
86 |
87 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
88 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
89 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
90 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
91 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
92 | fi
93 | rm -f "$RESOURCES_TO_COPY"
94 |
95 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
96 | then
97 | # Find all other xcassets (this unfortunately includes those of path pods and other targets).
98 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
99 | while read line; do
100 | if [[ $line != "${PODS_ROOT}*" ]]; then
101 | XCASSET_FILES+=("$line")
102 | fi
103 | done <<<"$OTHER_XCASSETS"
104 |
105 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
106 | fi
107 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-ExampleTests/Pods-NotchToolkit-ExampleTests-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_NotchToolkit_ExampleTestsVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_NotchToolkit_ExampleTestsVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-ExampleTests/Pods-NotchToolkit-ExampleTests.debug.xcconfig:
--------------------------------------------------------------------------------
1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/NotchToolkit"
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
4 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/NotchToolkit/NotchToolkit.framework/Headers"
5 | PODS_BUILD_DIR = $BUILD_DIR
6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
8 | PODS_ROOT = ${SRCROOT}/Pods
9 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-ExampleTests/Pods-NotchToolkit-ExampleTests.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_NotchToolkit_ExampleTests {
2 | umbrella header "Pods-NotchToolkit-ExampleTests-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-NotchToolkit-ExampleTests/Pods-NotchToolkit-ExampleTests.release.xcconfig:
--------------------------------------------------------------------------------
1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/NotchToolkit"
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
4 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/NotchToolkit/NotchToolkit.framework/Headers"
5 | PODS_BUILD_DIR = $BUILD_DIR
6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
8 | PODS_ROOT = ${SRCROOT}/Pods
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Ahmed Fathi Bekhit[me@ahmedbekhit.com]
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 |
--------------------------------------------------------------------------------
/NotchToolkit.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 |
3 | s.name = "NotchToolkit"
4 | s.version = "1.3"
5 | s.summary = "An iOS framework for iPhone X notch."
6 |
7 | s.description = "A framework for iOS that allow developers use the iPhone X notch space in creative ways."
8 |
9 | s.homepage = "https://github.com/AFathi/NotchToolkit"
10 | s.screenshots = "http://ahmedbekhit.com/toolbar_preview.gif"
11 | s.license = { :type => "MIT", :file => "LICENSE" }
12 |
13 | s.author = { "Ahmed Bekhit" => "me@ahmedbekhit.com" }
14 | s.social_media_url = "http://twitter.com/iAFapps"
15 |
16 | s.platform = :ios, "11.0"
17 |
18 | s.source = { :git => "https://github.com/AFathi/NotchToolkit.git", :tag => "1.3" }
19 |
20 | s.source_files = "NotchToolkit", "NotchToolkit/**/*.{swift}"
21 |
22 | end
--------------------------------------------------------------------------------
/NotchToolkit.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/NotchToolkit.xcodeproj/xcshareddata/xcschemes/NotchToolkit.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
34 |
40 |
41 |
42 |
43 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
66 |
67 |
73 |
74 |
75 |
76 |
77 |
78 |
84 |
85 |
91 |
92 |
93 |
94 |
96 |
97 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/NotchToolkit/Cells/NotchToolCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolCell.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class NotchToolCell: UICollectionViewCell {
12 | private var toolIcon : UIImageView?
13 | private var toolTitle : UILabel?
14 |
15 | func setIcon(_ image:UIImage?) {
16 | if toolIcon == nil {
17 | toolIcon = UIImageView()
18 | toolIcon?.frame = CGRect(x: 0, y:0, width: contentView.frame.width, height: contentView.frame.height)
19 | toolIcon?.contentMode = .scaleAspectFit
20 | contentView.addSubview(toolIcon!)
21 | }
22 |
23 | if let icon = toolIcon {
24 | if let img = image {
25 | icon.image = img
26 | }
27 | icon.isHidden = false
28 | }
29 | if let title = toolTitle {
30 | title.isHidden = true
31 | }
32 | }
33 |
34 | func setTitle(_ text:String, font:UIFont, color:UIColor) {
35 | if toolTitle == nil {
36 | toolTitle = UILabel()
37 | toolTitle?.frame = CGRect(x: 0, y: 0, width: contentView.frame.width, height: contentView.frame.height)
38 | toolTitle?.font = font
39 | toolTitle?.textColor = color
40 | toolTitle?.textAlignment = .center
41 | contentView.addSubview(toolTitle!)
42 | }
43 |
44 | if let title = toolTitle {
45 | title.text = text
46 | title.isHidden = false
47 | }
48 |
49 | if let icon = toolIcon {
50 | icon.isHidden = true
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/NotchToolkit/Cells/NotchToolNameIconCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolNameIconCell.swift
3 | // NotchToolkit
4 | //
5 | // Created by Ahmed Bekhit on 9/28/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class NotchToolNameIconCell: UICollectionViewCell {
12 | private var toolIcon : UIImageView?
13 | private var toolTitle : UILabel?
14 |
15 | func set(_ image:UIImage? = nil, text:String? = nil, font:UIFont? = nil, color:UIColor? = nil, type: toolIconTypes) {
16 | var titleFrame:CGRect!
17 | var iconFrame:CGRect!
18 |
19 | var isTitleHidden:Bool!
20 | var isIconHidden:Bool!
21 |
22 | switch type {
23 | case .image:
24 | titleFrame = CGRect(x: 0, y: 0, width: contentView.frame.width, height: contentView.frame.height)
25 | iconFrame = CGRect(x: 0, y: 0, width: contentView.frame.width, height: contentView.frame.height)
26 | isTitleHidden = true
27 | isIconHidden = false
28 | case .text:
29 | titleFrame = CGRect(x: 0, y: 0, width: contentView.frame.width, height: contentView.frame.height)
30 | iconFrame = CGRect(x: 0, y: 0, width: contentView.frame.width, height: contentView.frame.height)
31 | isTitleHidden = false
32 | isIconHidden = true
33 | case .both:
34 | titleFrame = CGRect(x: 0, y: contentView.frame.height*0.75, width: contentView.frame.width, height: contentView.frame.height*0.25)
35 | iconFrame = CGRect(x: 0, y:0, width: contentView.frame.width, height: contentView.frame.height*0.75)
36 | isTitleHidden = false
37 | isIconHidden = false
38 | }
39 |
40 | if toolTitle == nil {
41 | toolTitle = UILabel()
42 | toolTitle?.frame = titleFrame
43 | if let font = font {
44 | toolTitle?.font = font
45 | }
46 | if let color = color {
47 | toolTitle?.textColor = color
48 | }
49 | toolTitle?.textAlignment = .center
50 | contentView.addSubview(toolTitle!)
51 | }
52 |
53 | if toolIcon == nil {
54 | toolIcon = UIImageView()
55 | toolIcon?.frame = iconFrame
56 | toolIcon?.contentMode = .scaleAspectFit
57 | contentView.addSubview(toolIcon!)
58 | }
59 | if let title = toolTitle {
60 | if let txt = text {
61 | title.text = txt
62 | }
63 | title.isHidden = isTitleHidden
64 | }
65 | if let icon = toolIcon {
66 | if let img = image {
67 | icon.image = img
68 | }
69 | icon.isHidden = isIconHidden
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/NotchToolkit/Classes/NotchBar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchBar.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | public class NotchBar: UIView {
11 | /**
12 | This allows you to choose between statusBar & noStatusBar modes.
13 | */
14 | public var mode:notchMode = .statusBar
15 | /**
16 | This allows you to set the height of the NotchBar.
17 | */
18 | public var height:CGFloat = 250
19 | /**
20 | This allows you to set the background color of the NotchBar.
21 | */
22 | public var bgColor:UIColor = .black
23 | /**
24 | This allows you to set the corner radii of the NotchBar.
25 | */
26 | public var curve:CGFloat = 35
27 | /**
28 | This allows you to initially set the NotchBar visibility.
29 | */
30 | public var isVisible:Bool = false
31 | /**
32 | This allows you to set the animation show/hide & rotation animation time interval of the NotchBar.
33 | */
34 | public var animationInterval:TimeInterval = 0.3
35 |
36 | override init(frame: CGRect) {
37 | super.init(frame: frame)
38 | create()
39 | }
40 |
41 | required public init?(coder aDecoder: NSCoder) {
42 | super.init(coder: aDecoder)
43 | create()
44 | }
45 |
46 | var scale:CGFloat!
47 | var multiplier:CGFloat!
48 | func create() {
49 | switch mode {
50 | case .statusBar:
51 | scale = UIScreen.main.portraitNotch.width
52 | multiplier = UIScreen.main.multiplier
53 | case .noStatusBar:
54 | scale = UIScreen.main.widePortraitNotch.width
55 | multiplier = UIScreen.main.multiplierWide
56 | }
57 | self.bounds = CGRect(x: 0, y: 0, width: scale, height: height)
58 | self.center = CGPoint(x: UIScreen.main.portraitNotch.origin.x, y: (self.bounds.height/2))
59 | self.backgroundColor = bgColor
60 | self.draw(.corner, position: .bottom, curve: curve)
61 | self.layer.masksToBounds = true
62 | self.alpha = isVisible ? 1 : 0
63 | }
64 |
65 | /**
66 | This function is used to resize the NotchBar when device orientation is changed.
67 | */
68 | public func refresh(orientation:deviceOrientation) {
69 | let subtrehend = isVisible ? 0 : self.bounds.height
70 |
71 | switch mode {
72 | case .statusBar:
73 | scale = UIScreen.main.portraitNotch.width
74 | multiplier = UIScreen.main.multiplier
75 | case .noStatusBar:
76 | scale = UIScreen.main.widePortraitNotch.width
77 | multiplier = UIScreen.main.multiplierWide
78 | }
79 |
80 | switch orientation {
81 | case .portrait:
82 | UIView.animate(withDuration: animationInterval, animations: {
83 | self.bounds = CGRect(x: 0, y: 0, width: self.scale, height: self.height)
84 | self.center = CGPoint(x: UIScreen.main.portraitNotch.origin.x, y: (self.bounds.height/2) - subtrehend)
85 | self.backgroundColor = self.bgColor
86 | self.draw(.corner, position: .bottom, curve: self.curve)
87 | self.alpha = self.isVisible ? 1 : 0
88 | })
89 | case .landscapeLeft:
90 | UIView.animate(withDuration: animationInterval, animations: {
91 | self.bounds = CGRect(x: 0, y: 0, width: self.height, height: self.scale)
92 | self.center = CGPoint(x: (self.bounds.height*(self.multiplier*self.height)) - subtrehend, y: UIScreen.main.landscapeLeftNotch.origin.y)
93 | self.backgroundColor = self.bgColor
94 | self.draw(.corner, position: .right, curve: self.curve)
95 | self.alpha = self.isVisible ? 1 : 0
96 | })
97 | case .landscapeRight:
98 | UIView.animate(withDuration: animationInterval, animations: {
99 | self.bounds = CGRect(x: 0, y: 0, width: self.height, height: self.scale)
100 | self.center = CGPoint(x: (UIScreen.main.bounds.width-self.bounds.height*(self.multiplier*self.height)) + subtrehend, y: UIScreen.main.landscapeRightNotch.origin.y)
101 | self.backgroundColor = self.bgColor
102 | self.draw(.corner, position: .left, curve: self.curve)
103 | self.alpha = self.isVisible ? 1 : 0
104 | })
105 | }
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/NotchToolkit/Classes/NotchImageView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchImageView.swift
3 | // NotchToolkit
4 | //
5 | // Created by Ahmed Bekhit on 11/1/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | *NotchToolkit* is a framework for iOS that allow developers use the iPhones X notch space in creative ways.
13 |
14 | - Author: Ahmed Fathi Bekhit
15 | * [Github](http://github.com/AFathi)
16 | * [Website](http://ahmedbekhit.com)
17 | * [Twitter](http://twitter.com/iAFapps)
18 | * [Email](mailto:me@ahmedbekhit.com)
19 | */
20 | public class NotchImageView: NotchBar {
21 | // MARK: - Public objects
22 |
23 | /// This delegate is required to detect toolbar actions & automatically resize the NotchBar when device orientation is changed.
24 | public var delegate:NotchToolbarDelegate?
25 |
26 | /// This allows you to enable NotchToolbar only for iPhone X. Default is false.
27 | public var onlyFor10:Bool = false
28 | /// Configure printing bar height
29 | public var printBarHeight:CGFloat = 3
30 | /// Configure printing color
31 | public var printBarColor:UIColor = .cyan
32 | /// Configure image loading duration intervals
33 | public var durationIntervals:TimeInterval = 0.8
34 |
35 | // MARK: - Private Objects
36 | private var recentOrientation: deviceOrientation!
37 | private var imageView:UIImageView = UIImageView()
38 | private var notchImage:UIImage?
39 | private var printerBar:UIView = UIView()
40 | private var isShown:Bool = false
41 | private var isLoaded:Bool = false
42 |
43 | /// Initialize
44 | public init() {
45 | super.init(frame: CGRect.zero)
46 | }
47 | /// Initialize with a UIImage
48 | public init(image: UIImage?) {
49 | super.init(frame: CGRect.zero)
50 | notchImage = image
51 | self.bgColor = .clear
52 | self.animationInterval = 0.1
53 | }
54 |
55 | required public init?(coder aDecoder: NSCoder) {
56 | fatalError("init(coder:) has not been implemented")
57 | }
58 | }
59 |
60 | //MARK:- Methods
61 | extension NotchImageView {
62 | /// This method is required to prepare the NotchImageView in your view controller.
63 | public func prepare(in vc:UIViewController) {
64 | NotificationCenter.default.addObserver(vc, selector: #selector(delegate?.deviceDidRotate), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
65 | if onlyFor10 && !UIScreen.main.isiPhone10 {
66 | print("NotchToolbar: If you want to enable NotchToolBar on this device please add this line to your code\nNotchToolBar().onlyFor10 = false")
67 | }else{
68 | recentOrientation = .portrait
69 | imageView = UIImageView(frame: CGRect(x:0, y:0, width:self.bounds.width, height:self.bounds.height))
70 | imageView.center = CGPoint(x:(self.bounds.width)*0.5, y:-(self.bounds.height*0.5))
71 | imageView.backgroundColor = .clear
72 | imageView.contentMode = .scaleAspectFill
73 | imageView.clipsToBounds = true
74 | imageView.draw(.corner, position: .bottom, curve: self.curve)
75 | if let img = notchImage {
76 | imageView.image = img
77 | }
78 | self.addSubview(imageView)
79 |
80 | printerBar = UIView(frame: CGRect(x:0, y:0, width:self.bounds.width, height:printBarHeight))
81 | printerBar.center = CGPoint(x:self.bounds.width*0.5, y:-(self.bounds.height*0.5))
82 | printerBar.backgroundColor = printBarColor.withAlphaComponent(0.4)
83 | printerBar.layer.shadowColor = printBarColor.cgColor
84 | printerBar.layer.shadowOffset = CGSize(width: 0.0, height: 2.5)
85 | printerBar.layer.shadowOpacity = 1.0
86 | self.addSubview(printerBar)
87 |
88 | vc.view.addSubview(self)
89 | }
90 | }
91 | /// Loads image view from notch with animation
92 | public func load() {
93 | self.isVisible = true
94 |
95 | UIView.animate(withDuration: 0.3, delay: 0.1, usingSpringWithDamping: 1.2, initialSpringVelocity: 0.4, options: [.autoreverse, .repeat], animations: {
96 | self.printerBar.center = CGPoint(x:self.self.bounds.width*0.5, y:(self.self.bounds.height))
97 | })
98 |
99 | autoResize()
100 | isShown = true
101 | updateBounds(orientation: recentOrientation)
102 | }
103 | /// Removes image view from superview
104 | public func remove() {
105 | self.self.removeFromSuperview()
106 | self.removeFromSuperview()
107 | }
108 | /// This function is required to be called from the `deviceDidRotate` delegate function.
109 | public func autoResize() {
110 | switch UIDevice.current.orientation {
111 | case .portrait:
112 | recentOrientation = .portrait
113 | self.refresh(orientation: .portrait)
114 | self.updateBounds(orientation: .portrait)
115 | case .portraitUpsideDown:
116 | self.refresh(orientation: recentOrientation)
117 | self.updateBounds(orientation: recentOrientation)
118 | case .landscapeLeft:
119 | if UIScreen.main.bounds.size.width > UIScreen.main.bounds.height {
120 | recentOrientation = .landscapeLeft
121 | self.refresh(orientation: .landscapeLeft)
122 | self.updateBounds(orientation: .landscapeLeft)
123 | }
124 | case .landscapeRight:
125 | if UIScreen.main.bounds.size.width > UIScreen.main.bounds.height {
126 | recentOrientation = .landscapeRight
127 | self.refresh(orientation: .landscapeRight)
128 | self.updateBounds(orientation: .landscapeRight)
129 | }
130 | case .faceDown:
131 | self.refresh(orientation: recentOrientation)
132 | self.updateBounds(orientation: recentOrientation)
133 | case .faceUp:
134 | self.refresh(orientation: recentOrientation)
135 | self.updateBounds(orientation: recentOrientation)
136 | case .unknown:
137 | self.refresh(orientation: recentOrientation)
138 | self.updateBounds(orientation: recentOrientation)
139 | }
140 | }
141 |
142 | private func updateBounds(orientation: deviceOrientation) {
143 | var xPos = (self.bounds.width*0.5)
144 | var yPos = (self.bounds.height*0.5)
145 | switch orientation {
146 | case .landscapeLeft :
147 | xPos = (!isShown) ? -(self.bounds.width*0.5) : (self.bounds.width*0.5)
148 | case .landscapeRight:
149 | xPos = (!isShown) ? (self.bounds.width*1.5) : (self.bounds.width*0.5)
150 | case .portrait:
151 | yPos = (!isShown) ? -(self.bounds.height*0.5) : (self.bounds.height*0.5)
152 | }
153 |
154 | imageView.bounds = CGRect(x: 0, y: 0, width: self.bounds.size.width, height: self.bounds.size.height)
155 | if self.isLoaded{
156 | self.self.frame = UIScreen.main.bounds
157 | self.imageView.frame = self.self.frame
158 | self.self.draw(.corner, position: .bottom, curve: 0)
159 | self.imageView.draw(.corner, position: .bottom, curve: 0)
160 | return
161 | }
162 |
163 | UIView.animate(withDuration: self.durationIntervals, animations: {
164 | self.imageView.center = CGPoint(x:xPos, y:yPos)
165 | })
166 | if self.isShown {
167 | UIView.animate(withDuration: 0.4, delay: self.durationIntervals, usingSpringWithDamping: 0.4, initialSpringVelocity: 0.4, options: .curveLinear, animations: {
168 | self.self.frame = UIScreen.main.bounds
169 | self.imageView.frame = self.self.frame
170 | self.draw(.corner, position: .bottom, curve: 0)
171 | self.imageView.draw(.corner, position: .bottom, curve: 0)
172 | self.printerBar.alpha = 0
173 | }){ done in
174 | self.isLoaded = true
175 | self.printerBar.layer.removeAllAnimations()
176 | }
177 | }
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/NotchToolkit/Classes/NotchToolbar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolbar.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | *NotchToolkit* is a framework for iOS that allow developers use the iPhones X notch space in creative ways.
13 |
14 | - Author: Ahmed Fathi Bekhit
15 | * [Github](http://github.com/AFathi)
16 | * [Website](http://ahmedbekhit.com)
17 | * [Twitter](http://twitter.com/iAFapps)
18 | * [Email](mailto:me@ahmedbekhit.com)
19 | */
20 | public class NotchToolbar: NSObject, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate {
21 | /**
22 | This delegate is required to detect toolbar actions & automatically resize the NotchBar when device orientation is changed.
23 | */
24 | public var delegate:NotchToolbarDelegate?
25 | /**
26 | This provides you options to customize NotchBar.
27 | */
28 | public var notch:NotchBar = NotchBar()
29 | /**
30 | This gives you options to change the NotchToolbar scrolling directions. Default is auto.
31 | */
32 | public var scrollMode:notchScroll = .auto
33 |
34 | /**
35 | This allows you to enable NotchToolbar only for iPhone X. Default is false.
36 | */
37 | public var onlyFor10:Bool = false
38 | /**
39 | This is the collection view that loads the toolList.
40 | */
41 | public var tools:UICollectionView?
42 | /**
43 | This allows you to set the tool icon size. Default is 60x60
44 | */
45 | public var toolIconSize:CGSize = CGSize(width: 60, height: 60)
46 | /**
47 | This allows you to customize the collection view edge insets.
48 | */
49 | public var toolIconsInsets:UIEdgeInsets = UIEdgeInsetsMake(5, 35, 5, 35)
50 | /**
51 | This is the array of the tool icons in the NotchToolbar. You may use String, UIImage, or an array of both types.
52 | */
53 | public var toolList:[Any?] = ["🤓", "😊", "🙄", "👩🔬", "👨💻"]
54 | /**
55 | This allows you to customize the tools title font.
56 | */
57 | public var toolsTitleFont:UIFont = UIFont(name:"Avenir-Medium", size: 45)!
58 |
59 | /**
60 | This allows you to customize the tools image icon with title font.
61 | */
62 | public var iconWithNameFont:UIFont = UIFont(name:"Avenir-Medium", size: 12)!
63 |
64 | /**
65 | This allows you to customize the tools title color.
66 | */
67 | public var toolsTitleColor:UIColor = .white
68 |
69 | /**
70 | This allows you to customize the tools image icon with title color.
71 | */
72 | public var iconWithNameColor:UIColor = .white
73 |
74 | public var toolsFlow = UICollectionViewFlowLayout()
75 |
76 | private var recentOrientation: deviceOrientation!
77 |
78 | /**
79 | This function is required to initialize the NotchToolbar.
80 | */
81 | public func prepare(in vc:UIViewController) {
82 | NotificationCenter.default.addObserver(vc, selector: #selector(delegate?.deviceDidRotate), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
83 | if onlyFor10 && !UIScreen.main.isiPhone10 {
84 | print("NotchToolbar: If you want to enable NotchToolBar on this device please add this line to your code\nNotchToolBar().onlyFor10 = false")
85 | }else{
86 | switch scrollMode {
87 | case .alwaysHorizontal:
88 | toolsFlow.scrollDirection = .horizontal
89 | case .alwaysVertical:
90 | toolsFlow.scrollDirection = .vertical
91 | default:
92 | break
93 | }
94 | recentOrientation = .portrait
95 | tools = UICollectionView(frame: CGRect(x:0, y:0, width:notch.bounds.width, height:notch.bounds.height), collectionViewLayout: toolsFlow)
96 | tools?.register(NotchToolCell.self, forCellWithReuseIdentifier: "toolCell")
97 | tools?.register(NotchToolNameIconCell.self, forCellWithReuseIdentifier: "toolIconNameCell")
98 | tools?.delegate = self
99 | tools?.dataSource = self
100 | tools?.contentOffset = CGPoint(x: 0, y: 0)
101 | tools?.backgroundColor = .clear
102 | tools?.setContentOffset(CGPoint.zero, animated: false)
103 | notch.addSubview(tools!)
104 | vc.view.addSubview(notch)
105 | }
106 | }
107 |
108 | /**
109 | This function allows you to show and hide the NotchToolbar.
110 | */
111 | public func showOrHide() {
112 | notch.isVisible = notch.isVisible ? false : true
113 | autoResize()
114 | }
115 | }
116 |
117 | //MARK:- Methods and Delegates
118 | extension NotchToolbar {
119 | /**
120 | This function is required to be called from the `deviceDidRotate` delegate function.
121 | */
122 | public func autoResize() {
123 | var offsetPoint:CGPoint! = CGPoint.zero
124 | if UIScreen.main.bounds.size.width > UIScreen.main.bounds.height {
125 | switch scrollMode {
126 | case .auto:
127 | offsetPoint = CGPoint(x:-(pow(toolIconsInsets.top, 2.4)),y:0)
128 | toolsFlow.scrollDirection = .horizontal
129 | case .alwaysVertical:
130 | offsetPoint = CGPoint(x:-(pow(toolIconsInsets.top, 2.4)),y:0)
131 | default:
132 | break
133 | }
134 | }else{
135 | switch scrollMode {
136 | case .auto:
137 | offsetPoint = CGPoint(x:0,y:-(pow(toolIconsInsets.top, 2.4)))
138 | toolsFlow.scrollDirection = .vertical
139 | case .alwaysVertical:
140 | offsetPoint = CGPoint(x:0,y:-(pow(toolIconsInsets.top, 2.4)))
141 | default:
142 | break
143 | }
144 | }
145 |
146 | switch UIDevice.current.orientation {
147 | case .portrait:
148 | recentOrientation = .portrait
149 | notch.refresh(orientation: .portrait)
150 | tools?.bounds = CGRect(x: 0, y: 0, width: notch.bounds.size.width, height: notch.bounds.size.height)
151 | tools?.center = CGPoint(x: notch.bounds.size.width/2, y: notch.bounds.size.height/2)
152 | tools?.reloadData()
153 | tools?.setContentOffset(offsetPoint, animated: false)
154 | case .portraitUpsideDown:
155 | notch.refresh(orientation: recentOrientation)
156 | tools?.bounds = CGRect(x: 0, y: 0, width: notch.bounds.size.width, height: notch.bounds.size.height)
157 | tools?.center = CGPoint(x: notch.bounds.size.width/2, y: notch.bounds.size.height/2)
158 | tools?.reloadData()
159 | tools?.setContentOffset(offsetPoint, animated: false)
160 | case .landscapeLeft:
161 | if UIScreen.main.bounds.size.width > UIScreen.main.bounds.height {
162 | recentOrientation = .landscapeLeft
163 | notch.refresh(orientation: .landscapeLeft)
164 | tools?.bounds = CGRect(x: 0, y: 0, width: notch.bounds.size.width, height: notch.bounds.size.height)
165 | tools?.center = CGPoint(x: notch.bounds.size.width/2, y: notch.bounds.size.height/2)
166 | tools?.reloadData()
167 | tools?.setContentOffset(offsetPoint, animated: false)
168 | }
169 | case .landscapeRight:
170 | if UIScreen.main.bounds.size.width > UIScreen.main.bounds.height {
171 | recentOrientation = .landscapeRight
172 | notch.refresh(orientation: .landscapeRight)
173 | tools?.bounds = CGRect(x: 0, y: 0, width: notch.bounds.size.width, height: notch.bounds.size.height)
174 | tools?.center = CGPoint(x: notch.bounds.size.width/2, y: notch.bounds.size.height/2)
175 | tools?.reloadData()
176 | tools?.setContentOffset(offsetPoint, animated: false)
177 | }
178 | case .faceDown:
179 | notch.refresh(orientation: recentOrientation)
180 | tools?.bounds = CGRect(x: 0, y: 0, width: notch.bounds.size.width, height: notch.bounds.size.height)
181 | tools?.center = CGPoint(x: notch.bounds.size.width/2, y: notch.bounds.size.height/2)
182 | tools?.reloadData()
183 | tools?.setContentOffset(offsetPoint, animated: false)
184 | case .faceUp:
185 | notch.refresh(orientation: recentOrientation)
186 | tools?.bounds = CGRect(x: 0, y: 0, width: notch.bounds.size.width, height: notch.bounds.size.height)
187 | tools?.center = CGPoint(x: notch.bounds.size.width/2, y: notch.bounds.size.height/2)
188 | tools?.reloadData()
189 | tools?.setContentOffset(offsetPoint, animated: false)
190 | case .unknown:
191 | notch.refresh(orientation: recentOrientation)
192 | tools?.bounds = CGRect(x: 0, y: 0, width: notch.bounds.size.width, height: notch.bounds.size.height)
193 | tools?.center = CGPoint(x: notch.bounds.size.width/2, y: notch.bounds.size.height/2)
194 | tools?.reloadData()
195 | tools?.setContentOffset(offsetPoint, animated: false)
196 | }
197 | }
198 |
199 | public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
200 | return toolList.count
201 | }
202 |
203 | public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
204 | if let iconMultiple = toolList[indexPath.row] as? [Any] {
205 | let cell:NotchToolNameIconCell = collectionView.dequeueReusableCell(withReuseIdentifier: "toolIconNameCell", for: indexPath as IndexPath) as! NotchToolNameIconCell
206 |
207 | let extractedStrings = iconMultiple.filter{if let _ = $0 as? String{return true} else {return false}}
208 | let extractedImages = iconMultiple.filter{if let _ = $0 as? UIImage{return true} else {return false}}
209 |
210 | if let text = extractedStrings[0] as? String {
211 | if let image = extractedImages[0] as? UIImage {
212 | cell.set(image, text: text, font: iconWithNameFont, color: toolsTitleColor, type: .both)
213 | }
214 | }
215 | return cell
216 | }else{
217 | let cell:NotchToolCell = collectionView.dequeueReusableCell(withReuseIdentifier: "toolCell", for: indexPath as IndexPath) as! NotchToolCell
218 |
219 | if let text = toolList[indexPath.row] as? String {
220 | cell.setTitle(text, font: toolsTitleFont, color: toolsTitleColor)
221 | }else if let image = toolList[indexPath.row] as? UIImage {
222 | cell.setIcon(image)
223 | }
224 | return cell
225 | }
226 | }
227 |
228 | public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
229 | return toolIconSize
230 | }
231 |
232 | public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
233 | delegate?.didTapToolIcon(collectionView, toolIndex: indexPath, section: indexPath.section, row: indexPath.row)
234 | }
235 |
236 | public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
237 | return toolIconsInsets
238 | }
239 | }
240 |
--------------------------------------------------------------------------------
/NotchToolkit/Enumerations/CurveSettings.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CurveSettings.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | /**
10 | Types of bezier paths drawn in a view.
11 |
12 | `oval` Is an oval-based bezier path.
13 |
14 | `corner` Is a rounded-rectangle-based bezier path.
15 | */
16 | public enum curveType {
17 | /**
18 | `oval` Is an oval-based bezier path.
19 | */
20 | case oval
21 | /**
22 | `corner` Is a rounded-rectangle-based bezier path.
23 | */
24 | case corner
25 | }
26 |
27 | /**
28 | Position options to draw the bezier paths.
29 |
30 | `right` Draws a bezier path vertically on the right side of a view.
31 | - If **curveType** is `corner`, it draws a rounded rectangle corner on topRight and bottomRight of a view.
32 | - If **curveType** is `oval`, it draws an oval-based bezier path vertically on the right side of a view.
33 |
34 | `left` Draws a bezier path vertically on the left side of a view.
35 | - If **curveType** is `corner`, it draws a rounded rectangle corner on topLeft and bottomLeft of a view.
36 | - If **curveType** is `oval`, it draws an oval-based bezier path vertically on the left side of a view.
37 |
38 | `top` Draws a bezier path horizontally on the top side of a view.
39 | - If **curveType** is `corner`, it draws a rounded rectangle corner on topRight and topLeft of a view.
40 | - If **curveType** is `oval`, it draws an oval-based bezier path horizontally on the top side of a view.
41 |
42 | `bottom` Draws a bezier path vertically on the bottom side of a view.
43 | - If **curveType** is `corner`, it draws a rounded rectangle corner on bottomRight and bottomLeft of a view.
44 | - If **curveType** is `oval`, it draws an oval-based bezier path horizontally on the bottom side of a view.
45 |
46 | `horizontalSides` Draws an oval-based bezier path vertically on the right & left sides of a view.
47 | - Can only be applied when **curveType** is `oval`.
48 |
49 | `verticalSides` Draws an oval-based bezier path horizontally on the top & bottom sides of a view.
50 | - Can only be applied when **curveType** is `oval`.
51 |
52 | `all` Draws a bezier path on all sides of a view.
53 | - If **curveType** is `corner`, it draws rounded rectangle corners in topLeft, topRight, bottomLeft and bottomRight.
54 | - If **curveType** is `oval`, it draws a full oval shape out of the view.
55 | */
56 | public enum curvePosition {
57 | /**
58 | `right` Draws a bezier path vertically on the right side of a view.
59 | */
60 | case right
61 | /**
62 | `left` Draws a bezier path vertically on the left side of a view.
63 | */
64 | case left
65 | /**
66 | `top` Draws a bezier path horizontally on the top side of a view.
67 | */
68 | case top
69 | /**
70 | `bottom` Draws a bezier path vertically on the bottom side of a view.
71 | */
72 | case bottom
73 | /**
74 | `horizontalSides` Draws an oval-based bezier path vertically on the right & left sides of a view.
75 | */
76 | case horizontalSides
77 | /**
78 | `verticalSides` Draws an oval-based bezier path horizontally on the top & bottom sides of a view.
79 | */
80 | case verticalSides
81 | /**
82 | `diagonalAC` Draws rounded rectangle corners diagonally from topLeft to bottomRight of a view.
83 | */
84 | case diagonalAC
85 | /**
86 | `diagonalBD` Draws rounded rectangle corners diagonally from topRight to bottomLeft of a view.
87 | */
88 | case diagonalBD
89 | /**
90 | `all` Draws a bezier path on all sides of a view.
91 | */
92 | case all
93 | }
94 |
--------------------------------------------------------------------------------
/NotchToolkit/Enumerations/DeviceOrientation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DeviceOrientation.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | /**
10 | Types of the device orientation used to resize the NotchBar.
11 |
12 | `portrait` When the device's notch is on the top.
13 |
14 | `landscapeLeft` When the device's notch is on the left.
15 |
16 | `landscapeRight` When the device's notch is on the right.
17 |
18 | */
19 | public enum deviceOrientation {
20 | /**
21 | `portrait` When the device's notch is on the top.
22 | */
23 | case portrait
24 | /**
25 | `landscapeLeft` When the device's notch is on the left.
26 | */
27 | case landscapeLeft
28 | /**
29 | `landscapeRight` When the device's notch is on the right.
30 | */
31 | case landscapeRight
32 | }
33 |
--------------------------------------------------------------------------------
/NotchToolkit/Enumerations/NotchMode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchMode.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | /**
10 | Modes of the NotchBar based on status bar visibility.
11 | */
12 | public enum notchMode {
13 | /**
14 | This mode sets the width of the NotchBar as the iPhone's X notch width.
15 | */
16 | case statusBar
17 | /**
18 | This mode sets a wider width to display more content. Recommended for full landscape apps and when status bar is hidden.
19 | */
20 | case noStatusBar
21 | }
22 |
--------------------------------------------------------------------------------
/NotchToolkit/Enumerations/NotchScroll.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchScroll.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | /**
10 | Types of NotchToolbar scrolling directions.
11 |
12 | `alwaysHorizontal` sets scrolling direction to horizontal with all **deviceOriention** types.
13 |
14 | `alwaysVertical` sets scrolling direction to vertical with all **deviceOriention** types.
15 |
16 | `auto` sets scrolling direction to vertical when **deviceOriention** is `portrait` and horizontal when **deviceOriention** is `landscape`.
17 | */
18 |
19 | public enum notchScroll {
20 | /**
21 | `alwaysHorizontal` sets scrolling direction to horizontal with all **deviceOriention** types.
22 | */
23 | case alwaysHorizontal
24 | /**
25 | `alwaysVertical` sets scrolling direction to vertical with all **deviceOriention** types.
26 | */
27 | case alwaysVertical
28 | /**
29 | `auto` sets scrolling direction to vertical when **deviceOriention** is `portrait` and horizontal when **deviceOriention** is `landscape`.
30 | */
31 | case auto
32 | }
33 |
--------------------------------------------------------------------------------
/NotchToolkit/Enumerations/ToolIconTypes.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ToolIconTypes.swift
3 | // NotchToolkit
4 | //
5 | // Created by Ahmed Bekhit on 9/28/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | public enum toolIconTypes {
10 | case image
11 | case text
12 | case both
13 | }
14 |
--------------------------------------------------------------------------------
/NotchToolkit/Extensions/UIScreen+NotchFrame.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIScreen+NotchFrame.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension UIScreen {
12 | private func setNotchFrame(orientation:deviceOrientation, mode:notchMode) -> CGRect {
13 | var notchScale: CGFloat {
14 | switch mode {
15 | case .statusBar:
16 | if self.bounds.size.width > self.bounds.size.height {
17 | return self.bounds.size.height/1.8
18 | }else{
19 | return self.bounds.size.width/1.8
20 | }
21 | case .noStatusBar:
22 | if self.bounds.size.width > self.bounds.size.height {
23 | return self.bounds.size.height/1.5
24 | }else{
25 | return self.bounds.size.width/1.5
26 | }
27 | }
28 | }
29 |
30 | switch orientation {
31 | case .portrait:
32 | return CGRect(x: self.bounds.width/2, y: 0, width: notchScale, height: 0)
33 | case .landscapeLeft:
34 | return CGRect(x: 0, y: self.bounds.height/2, width: 0, height: notchScale)
35 | case .landscapeRight:
36 | return CGRect(x: 0, y: self.bounds.height/2, width: 0, height: notchScale)
37 | }
38 | }
39 |
40 | /**
41 | `portraitNotch` is a rectangle that returns the notch frame when **deviceOrientation** is `portrait`.
42 | */
43 | public var portraitNotch: CGRect {
44 | return setNotchFrame(orientation: .portrait, mode: .statusBar)
45 | }
46 | /**
47 | `landscapeLeftNotch` is a rectangle that returns the notch frame when **deviceOrientation** is `landscapeLeft`.
48 | */
49 | public var landscapeLeftNotch: CGRect {
50 | return setNotchFrame(orientation: .landscapeLeft, mode: .statusBar)
51 | }
52 | /**
53 | `landscapeRightNotch` is a rectangle that returns the notch frame when **deviceOrientation** is `landscapeRight`.
54 | */
55 | public var landscapeRightNotch: CGRect {
56 | return setNotchFrame(orientation: .landscapeRight, mode: .statusBar)
57 | }
58 |
59 | //Wider frame for .noStatusBar mode
60 | /**
61 | `widePortraitNotch` is a rectangle that returns a wider notch frame when **deviceOrientation** is `portrait`.
62 | */
63 | public var widePortraitNotch: CGRect {
64 | return setNotchFrame(orientation: .portrait, mode: .noStatusBar)
65 | }
66 | /**
67 | `wideLandscapeLeftNotch` is a rectangle that returns a wider notch frame when **deviceOrientation** is `landscapeLeft`.
68 | */
69 | public var wideLandscapeLeftNotch: CGRect {
70 | return setNotchFrame(orientation: .landscapeLeft, mode: .noStatusBar)
71 | }
72 | /**
73 | `wideLandscapeRightNotch` is a rectangle that returns a wider notch frame when **deviceOrientation** is `landscapeRight`.
74 | */
75 | public var wideLandscapeRightNotch: CGRect {
76 | return setNotchFrame(orientation: .landscapeRight, mode: .noStatusBar)
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/NotchToolkit/Extensions/UIScreen+NotchPositionMultiplier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIScreen+NotchPositionMultiplier.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension UIScreen {
12 | private func setMultiplier(mode:notchMode) -> CGFloat {
13 | switch mode {
14 | case .statusBar:
15 | return 0.0021
16 | case .noStatusBar:
17 | return 0.0017
18 | }
19 | }
20 | /**
21 | `multiplier` is a float number that's used to postion the NotchBar when **deviceOrientation** is landscape.
22 | */
23 | public var multiplier: CGFloat {
24 | return setMultiplier(mode: .statusBar)
25 | }
26 | /**
27 | `multiplierWide` is a float number that's used to postion the wide NotchBar when **deviceOrientation** is landscape.
28 | */
29 | public var multiplierWide: CGFloat {
30 | return setMultiplier(mode: .noStatusBar)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/NotchToolkit/Extensions/UIScreen+iPhone10.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIScreen+iPhone10.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | public extension UIScreen {
11 | /**
12 | `isiPhone10` is a boolean that returns if the device is iPhone X or not.
13 | */
14 | public var isiPhone10: Bool {
15 | return self.nativeBounds.size == CGSize(width: 1125, height: 2436)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/NotchToolkit/Extensions/UIView+DrawNotch.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+OvalOrCorners.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/23/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension UIView {
12 | /**
13 | **UIView.draw(notch type,position,curve,customBounds)** is a UIView extension that allows you add ovals and rounded corners to a UIView.
14 | - For type `oval`, set `curve` from 1.0 - 10.0.
15 | - For type `corner`, `curve` is the radius size.
16 | - Check `curveType` & `curvePosition` for more info.
17 | */
18 | public func draw(_ notch:curveType, position:curvePosition, curve:CGFloat?, customBounds:CGRect? = nil) {
19 | let offset:CGFloat = self.frame.size.width/curve!
20 | var bounds:CGRect!
21 | var viewBounds:CGRect!
22 | var viewPath:UIBezierPath!
23 |
24 | if let finalBounds = customBounds {
25 | bounds = finalBounds
26 | }else{
27 | bounds = self.bounds
28 | }
29 |
30 | switch notch {
31 | case .oval:
32 | var ovalBounds:CGRect!
33 | switch position {
34 | case .right:
35 | ovalBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y - offset / 2, width:bounds.size.width , height:bounds.size.height + offset)
36 | viewBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.size.width/2, height: bounds.size.height)
37 |
38 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
39 | viewPath = UIBezierPath(rect: viewBounds)
40 | viewPath.append(ovalPath)
41 | break
42 | case .left:
43 | ovalBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y - offset / 2, width:bounds.size.width , height:bounds.size.height + offset)
44 | viewBounds = CGRect(x: bounds.origin.x+bounds.size.width/2, y: bounds.origin.y, width: bounds.size.width/2, height: bounds.size.height)
45 |
46 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
47 | viewPath = UIBezierPath(rect: viewBounds)
48 | viewPath.append(ovalPath)
49 | break
50 | case .top:
51 | ovalBounds = CGRect(x: bounds.origin.x - offset / 2, y: bounds.origin.y, width:bounds.size.width + offset, height:bounds.size.height)
52 | viewBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y + bounds.size.height / 2, width: bounds.size.width, height: bounds.size.height / 2)
53 |
54 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
55 | viewPath = UIBezierPath(rect: viewBounds)
56 | viewPath.append(ovalPath)
57 | break
58 | case .bottom:
59 | ovalBounds = CGRect(x: bounds.origin.x - offset / 2, y: bounds.origin.y, width:bounds.size.width + offset, height:bounds.size.height)
60 | viewBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.size.width, height: bounds.size.height / 2)
61 |
62 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
63 | viewPath = UIBezierPath(rect: viewBounds)
64 | viewPath.append(ovalPath)
65 | break
66 | case .horizontalSides:
67 | ovalBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y - offset / 2, width:bounds.size.width , height:bounds.size.height + offset)
68 | viewBounds = CGRect(x: bounds.origin.x+bounds.size.width, y: bounds.origin.y+bounds.size.height, width: bounds.size.width, height: bounds.size.height)
69 |
70 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
71 | viewPath = UIBezierPath(rect: viewBounds)
72 | viewPath.append(ovalPath)
73 | break
74 | case .verticalSides:
75 | ovalBounds = CGRect(x: bounds.origin.x - offset / 2, y: bounds.origin.y, width:bounds.size.width + offset, height:bounds.size.height)
76 | viewBounds = CGRect(x: bounds.origin.x+bounds.size.width, y: bounds.origin.y+bounds.size.height, width: bounds.size.width, height: bounds.size.height)
77 |
78 | let ovalPath = UIBezierPath(ovalIn: ovalBounds)
79 | viewPath = UIBezierPath(rect: viewBounds)
80 | viewPath.append(ovalPath)
81 | break
82 | case .all:
83 | viewPath = UIBezierPath(ovalIn: self.bounds)
84 | break
85 | default:
86 | break
87 | }
88 | break
89 | case .corner:
90 | switch position {
91 | case .right:
92 |
93 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topRight, .bottomRight], cornerRadii: CGSize(width:curve!, height:curve!))
94 | break
95 | case .left:
96 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .bottomLeft], cornerRadii: CGSize(width:curve!, height:curve!))
97 | break
98 | case .top:
99 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width:curve!, height:curve!))
100 | break
101 | case .bottom:
102 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width:curve!, height:curve!))
103 | break
104 | case .diagonalAC:
105 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .bottomRight], cornerRadii: CGSize(width:curve!, height:curve!))
106 | break
107 | case .diagonalBD:
108 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topRight, .bottomLeft], cornerRadii: CGSize(width:curve!, height:curve!))
109 | break
110 | case .all:
111 | viewPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.allCorners], cornerRadii: CGSize(width:curve!, height:curve!))
112 | break
113 | default:
114 | break
115 | }
116 | break
117 | }
118 | if let path = viewPath {
119 | let shapeLayer: CAShapeLayer = CAShapeLayer()
120 | shapeLayer.frame = bounds
121 | shapeLayer.path = path.cgPath
122 | self.layer.mask = shapeLayer
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/NotchToolkit/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.3
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/NotchToolkit/NotchToolkit.h:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolkit.h
3 | // NotchToolkit
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for NotchToolkit.
12 | FOUNDATION_EXPORT double NotchToolkitVersionNumber;
13 |
14 | //! Project version string for NotchToolkit.
15 | FOUNDATION_EXPORT const unsigned char NotchToolkitVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/NotchToolkit/Protocols/NotchToolbarDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolbarDelegate.swift
3 | // NotchToolbar
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | /**
11 | This delegate is required to detect toolbar actions & automatically resize the NotchBar when device orientation is changed.
12 | */
13 | @objc public protocol NotchToolbarDelegate {
14 | /**
15 | This delegate function detects when the device orientation changes. Calling **autoResize()** function inside this delegate is **required**.
16 | */
17 | func deviceDidRotate()
18 | /**
19 | This delegate function allows you to detect which toolbar icon was selected.
20 | */
21 | func didTapToolIcon(_ tools: UICollectionView, toolIndex:IndexPath, section: Int, row: Int)
22 | }
23 |
--------------------------------------------------------------------------------
/NotchToolkitTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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 |
--------------------------------------------------------------------------------
/NotchToolkitTests/NotchToolkitTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotchToolkitTests.swift
3 | // NotchToolkitTests
4 | //
5 | // Created by Ahmed Bekhit on 9/25/17.
6 | // Copyright © 2017 Ahmed Fathi Bekhit. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import NotchToolkit
11 |
12 | class NotchToolkitTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NotchToolkit
2 | NotchToolkit is a framework for iOS that allow developers use the iPhone X notch space in creative ways.
3 | Inspired by
4 |
5 | | Table of Contents | Description |
6 | | ------------------ |:------------------:|
7 | | [Documentation](https://github.com/AFathi/NotchToolkit/wiki) | Describes the configuration options `NotchToolkit` offers |
8 | | [Preview](#preview) | Displays preview images of `NotchToolkit` features |
9 | | [Compatibility](#compatibility) | Describes the `NotchToolkit` device and iOS compatibality |
10 | | [Example Project](#example-project) | Explains how to run the example project provided in this repository |
11 | | [Installation](#installation) | Describes the [CocoaPods](#cocoapods), [Carthage](#carthage), and [Manual](#manual) options to install `NotchToolkit` |
12 | | [Implementation](#implement-in-your-project) | Lists the steps needed to implement `NotchToolkit` into your project |
13 | | [More Options](#more-options) | Describes an extra feature `NotchToolkit` supports |
14 | | [License](#license) | Describes `NotchToolkit` license |
15 |
16 | ## Preview
17 | [**NotchImageView**](https://github.com/AFathi/NotchToolkit/wiki/NotchImageView)
18 |
19 | 
20 |
21 |
22 | [**NotchToolbar**](https://github.com/AFathi/NotchToolkit/wiki/NotchToolbar)
23 |
24 | 
25 |
26 |
27 | [**Draw Notch**](#more-options)
28 |
29 | 
30 |
31 | ## Compatibility
32 | Although `NotchToolkit` is made for iPhone X, it can be implemented in older iPhone devices. This framework was tested on:
33 |
34 | 1. iPhone X
35 | 2. iPhone 8 plus, 7 plus, 6s plus and 6 plus
36 | 3. iPhone 8, 7, 6s and 6
37 | 4. iPhone SE and 5s
38 |
39 | `NotchToolkit` requires
40 |
41 | - iOS 11
42 | - Swift 3.2 or higher
43 |
44 | `NotchToolkit` has options to customize your Toolbar and UIView,
45 |
46 | check [**Documentation**](https://github.com/AFathi/NotchToolkit/wiki) and [**More Options**](#more-options) for more details.
47 |
48 | ## Example Project
49 | To try the example project, simply download this repo then open `NotchToolkit-Example.xcworkspace` project file, found in the `Example` folder.
50 |
51 | ## Installation
52 | ### CocoaPods
53 | 1. Download [CocoaPods](http://cocoapods.org) using this command in `Terminal`
54 | ```
55 | $ sudo gem install cocoapods
56 | ```
57 | 2. Redirect to your project folder in `Terminal`
58 | ```
59 | $ cd YOUR_PROJECT_FILE_PATH
60 | ```
61 | 3. Initialize a pod in `Terminal`
62 | ```
63 | $ pod init
64 | ```
65 | 4. Open Podfile in a text editor and add this line
66 | ```
67 | pod 'NotchToolkit'
68 | ```
69 | 5. Go back to `Terminal` and install the pod
70 | ```
71 | $ pod install
72 | ```
73 | ### Carthage
74 | 1. Add this line to the `Cartfile` in your project directory
75 | ```
76 | github "AFathi/NotchToolkit"
77 | ```
78 | 2. Update your Carthage directory
79 | ```
80 | $ carthage update
81 | ```
82 | ### Manual
83 | Drag the `NotchToolkit.xcodeproj` file into your project then add `NotchToolkit` as an embedded binary of your targets.
84 |
85 | ## Implement in your project
86 | 1. `import NotchToolkit` in a `UIViewController` class
87 | 2. Add [`NotchToolbarDelegate`](https://github.com/AFathi/NotchToolkit/wiki/NotchToolbarDelegate) in the delegate section
88 | ```
89 | class ViewController: UIViewController, NotchToolbarDelegate
90 | ```
91 | 3. Add delegate methods
92 | ```
93 | //A protocol method that's triggered when the device rotates.
94 | func deviceDidRotate() {
95 | }
96 |
97 | //A protocol method that's triggered when an icon is selected.
98 | func didTapToolIcon(_ tools: UICollectionView, toolIndex: IndexPath, section: Int, row: Int) {
99 | }
100 | ```
101 | 4. Create a [`NotchToolbar`](https://github.com/AFathi/NotchToolkit/wiki/NotchToolbar) global variable
102 | ```
103 | let toolbar = NotchToolbar()
104 | ```
105 | 5. Configure and initialize `toolbar` in `viewDidLoad`
106 | ```
107 | toolbar.notch.isVisible = true
108 |
109 | toolbar.notch.height = 250
110 |
111 | toolbar.toolList = [
112 | //[icon image, title]
113 | [UIImage(named:"pikachusquare")!, "Pikachu"],
114 | //only image icons
115 | UIImage(named:"spongebob")!,
116 | //only string icons (mainly for emojis 😉)
117 | "🤔", "🤓",
118 | "📱", "👩💻",
119 | "👨💻", "✅", "🔥"]
120 |
121 | toolbar.delegate = self
122 | toolbar.initializeToolbar(self)
123 | ```
124 | 6. Call [`autoResize()`](https://github.com/AFathi/NotchToolkit/wiki/NotchToolbar#func-autoresize) method in the [`deviceDidRotate`](https://github.com/AFathi/NotchToolkit/wiki/NotchToolbarDelegate#func-devicedidrotate) delegate method
125 | ```
126 | func deviceDidRotate() {
127 | toolbar.autoResize()
128 | }
129 | ```
130 | **You're all set! 🤓**
131 | ## Show and Hide `toolbar`
132 | ### [showOrHide()](https://github.com/AFathi/NotchToolkit/wiki/NotchToolbar#func-showorhide)
133 | This method allows you to show and hide the `NotchToolbar`. You can call this method in an `IBAction` that handles showing/hiding the toolbar.
134 | ```
135 | @IBAction func buttonClicked(_ sender: UIButton) {
136 | toolbar.showOrHide()
137 | }
138 | ```
139 | ## Handle Icon Selection
140 | 1. Make sure you set the [`NotchToolbar`](https://github.com/AFathi/NotchToolkit/wiki/NotchToolbar) delegate to `self`.
141 | 2. Handle the icon selection in the [`didTapToolIcon`](https://github.com/AFathi/NotchToolkit/wiki/NotchToolbarDelegate#func-didtaptoolicon_-tools-uicollectionview-toolindexindexpath-section-int-row-int) delegate method:
142 | ```
143 | func didTapToolIcon(_ tools: UICollectionView, toolIndex: IndexPath, section: Int, row: Int) {
144 | if row == 0 {
145 | print("first icon")
146 | }else if row == 1 {
147 | print("second icon")
148 | }
149 | }
150 | ```
151 | ## More Options
152 | This framework include a `UIView` extension that allow you draw a notch bezier path to any `UIView` class or subclass.
153 | ### draw(_ notch:curveType, position:curvePosition, curve:CGFloat?, customBounds:CGRect? = nil)
154 | This is a UIView extension that allows you add ovals and rounded corners to any UIView.
155 |
156 | - For type `oval`, set `curve` scale from 1.0 - 10.0.
157 | - For type `corner`, `curve` is the radius size.
158 | - Check `curveType` & `curvePosition` for more info.
159 | ### Example
160 | ```
161 | //horizontalSides draws an oval-based bezier path vertically on the right & left sides of a view.
162 | myView.draw(.oval, position: .horizontalSides, curve: 1.5)
163 |
164 | //diagonalAC draws rounded rectangle corners diagonally from topLeft to bottomRight of a view.
165 | myView.draw(.corner, position: .diagonalAC, curve: 35)
166 |
167 | ```
168 | ### Preview
169 | 
170 |
171 | ## LICENSE
172 | `NotchToolkit` is under MIT license. Check the [LICENSE](LICENSE) file for more details.
173 |
174 |
--------------------------------------------------------------------------------
/drawNotch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFathi/NotchToolkit/d8c0e69c440df88eb7f66103a6e01ebc24506f74/drawNotch.gif
--------------------------------------------------------------------------------