├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ └── ci.yml
├── .gitignore
├── .swiftlint.yml
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Example.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ └── Example.xcscheme
├── Example
├── AppDelegate.swift
├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── appIcon20pt@2x.png
│ │ ├── appIcon20pt@3x.png
│ │ ├── appIcon29pt@2x.png
│ │ ├── appIcon29pt@3x.png
│ │ ├── appIcon40pt@2x.png
│ │ ├── appIcon40pt@3x.png
│ │ ├── appIcon60pt@2x.png
│ │ └── appIcon60pt@3x.png
│ ├── Contents.json
│ ├── periscope
│ │ ├── Contents.json
│ │ └── pe-background.imageset
│ │ │ ├── Contents.json
│ │ │ └── IMG_3582.png
│ ├── skype
│ │ ├── Contents.json
│ │ └── skype-background.imageset
│ │ │ ├── Contents.json
│ │ │ └── skype-background@2x.png
│ ├── spotify
│ │ ├── Contents.json
│ │ ├── sp-add-icon.imageset
│ │ │ ├── Contents.json
│ │ │ └── sp-add-icon@2x.png
│ │ ├── sp-background.imageset
│ │ │ ├── Contents.json
│ │ │ └── IMG_3579.png
│ │ ├── sp-header-icon.imageset
│ │ │ ├── Contents.json
│ │ │ └── sp-header-icon@2x.png
│ │ ├── sp-radio-icon.imageset
│ │ │ ├── Contents.json
│ │ │ └── sp-radio-icon@2x.png
│ │ ├── sp-remove-icon.imageset
│ │ │ ├── Contents.json
│ │ │ └── sp-remove-icon@2x.png
│ │ ├── sp-share-icon.imageset
│ │ │ ├── Contents.json
│ │ │ └── sp-share-icon@2x.png
│ │ └── sp-view-album-icon.imageset
│ │ │ ├── Contents.json
│ │ │ └── sp-view-album-icon@2x.png
│ ├── tweetbot
│ │ ├── Contents.json
│ │ └── tb-background.imageset
│ │ │ ├── Contents.json
│ │ │ └── IMG_3578.png
│ ├── twitter
│ │ ├── Contents.json
│ │ ├── tw-background.imageset
│ │ │ ├── Contents.json
│ │ │ └── IMG_3577.png
│ │ ├── tw-remer.imageset
│ │ │ ├── Contents.json
│ │ │ └── tw-remer.jpg
│ │ └── tw-xmartlabs.imageset
│ │ │ ├── Contents.json
│ │ │ └── tw-xmartlabs.png
│ ├── xmartlabs
│ │ ├── Contents.json
│ │ ├── xl_header.imageset
│ │ │ ├── Contents.json
│ │ │ └── header.png
│ │ └── xmartlabs_logo.imageset
│ │ │ ├── Contents.json
│ │ │ └── xmartlabsLogoCircle@2x.png
│ └── youtube
│ │ ├── Contents.json
│ │ ├── yt-add-to-playlist-icon.imageset
│ │ ├── Contents.json
│ │ └── yt-add-to-playlist-icon.png
│ │ ├── yt-add-to-watch-later-icon.imageset
│ │ ├── Contents.json
│ │ └── yt-add-watch-later-icon.png
│ │ ├── yt-background.imageset
│ │ ├── Contents.json
│ │ └── IMG_3581.png
│ │ ├── yt-cancel-icon.imageset
│ │ ├── Contents.json
│ │ └── yt-cancel-icon.png
│ │ └── yt-share-icon.imageset
│ │ ├── Contents.json
│ │ └── yt-share-icon.png
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── CustomActionControllers
│ ├── Periscope
│ │ ├── Periscope.swift
│ │ └── PeriscopeCell.xib
│ ├── Skype
│ │ ├── Skype.swift
│ │ └── SkypeCell.xib
│ ├── Spotify
│ │ ├── Spotify.swift
│ │ └── SpotifyCell.xib
│ ├── Tweetbot
│ │ ├── Tweetbot.swift
│ │ └── TweetbotCell.xib
│ ├── Twitter
│ │ ├── Twitter.swift
│ │ └── TwitterCell.xib
│ └── Youtube
│ │ ├── Youtube.swift
│ │ └── YoutubeCell.xib
├── Info.plist
├── MainViewController.swift
├── PeriscopeExampleViewController.swift
├── SkypeExampleViewController.swift
├── SpotifyExampleViewController.swift
├── TweetbotExampleViewController.swift
├── TwitterExampleViewController.swift
├── UITests
│ ├── ExampleUITests.swift
│ └── Info.plist
└── YouTubeExampleViewController.swift
├── LICENSE
├── Media
├── demo_periscope.gif
├── demo_skype.gif
├── demo_spotify.gif
├── demo_tweetbot.gif
├── demo_twitter.gif
└── demo_youtube.gif
├── Package.swift
├── README.md
├── Resource
└── ActionCell.xib
├── Source
├── Action.swift
├── ActionCell.swift
├── ActionController.swift
├── ActionControllerSettings.swift
├── ActionData.swift
├── DynamicCollectionViewFlowLayout.swift
├── Info.plist
└── XLActionController.h
├── Tests
├── Info.plist
└── XLActionControllerTests.swift
├── XLActionController.png
├── XLActionController.podspec
├── XLActionController.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ └── XLActionController.xcscheme
└── XLActionController.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
└── IDEWorkspaceChecks.plist
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: xmartlabs # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Before submitting issues ...
2 |
3 | - Make sure you are using XLActionController [latest release](https://github.com/xmartlabs/XLActionController/releases) or master branch version.
4 | - Make sure your Xcode version is the latest stable one.
5 | - Check if the issue was [already reported or fixed](https://github.com/xmartlabs/XLActionController/issues?utf8=%E2%9C%93&q=is%3Aissue). We add labels to each issue in order to easily find related issues. If you found a match add a brief comment "I have the same problem" or "+1".
6 |
7 | When submitting issues, please provide the following information to help maintainers to fix the problem faster:
8 |
9 | - Environment: XLActionController, Xcode and iOS version you are using.
10 | - In case of reporting errors, provide Xcode console output of stack trace or code compilation error.
11 | - Any other additional detail such as example code that you think it would be useful to understand, reproduce and solve the problem.
12 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/.github/PULL_REQUEST_TEMPLATE.md
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: XLActionController CI
2 |
3 | on:
4 | pull_request:
5 | push:
6 | branches:
7 | - master
8 |
9 | jobs:
10 | iOS:
11 | runs-on: macOS-latest
12 | strategy:
13 | matrix:
14 | destination: ['platform=iOS Simulator,OS=14.4,name=iPhone 11']
15 | steps:
16 | - uses: actions/checkout@v2
17 | - name: Build and test library
18 | run: set -o pipefail && xcodebuild -project XLActionController.xcodeproj -scheme 'XLActionController' -sdk 'iphonesimulator' -destination "${{ matrix.destination }}" -configuration Debug ONLY_ACTIVE_ARCH=NO test | xcpretty -c
19 | - name: Build Example Debug
20 | run: set -o pipefail && xcodebuild -project Example.xcodeproj -scheme 'Example' -sdk 'iphonesimulator' -destination "${{ matrix.destination }}" -configuration Debug ONLY_ACTIVE_ARCH=NO build | xcpretty -c
21 | - name: Build Example Release
22 | run: set -o pipefail && xcodebuild -project Example.xcodeproj -scheme 'Example' -sdk 'iphonesimulator' -destination "${{ matrix.destination }}" -configuration Release ONLY_ACTIVE_ARCH=NO build | xcpretty -c
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | .DS_Store
3 | */build/*
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | profile
14 | *.moved-aside
15 | DerivedData
16 | .idea/
17 | *.hmap
18 | *.xccheckout
19 | .build/
20 |
21 | #CocoaPods
22 | Pods
23 | Tests/Pods
24 | Tests/Podfile.lock
25 | Examples/Objective-C/Podfile.lock
26 | Examples/Swift/Podfile.lock
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | included:
2 | - Source
3 | - Example
4 | disabled_rules:
5 | #- colon
6 | #- control_statement
7 | - file_length
8 | - force_cast
9 | - function_body_length
10 | #- leading_whitespace
11 | - line_length
12 | #- nesting
13 | #- operator_whitespace
14 | #- return_arrow_whitespace
15 | #- todo
16 | #- trailing_newline
17 | - trailing_whitespace
18 | - type_body_length
19 | #- type_name
20 | #- variable_name
21 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | ### [5.1.0](https://github.com/xmartlabs/XLActionController/releases/tag/5.1.0)
6 |
7 | * Added the ability to adjust Cancel View's Title font and size. (#145)
8 | * Support for SPM (#144, #146)
9 |
10 | ### [5.0.2](https://github.com/xmartlabs/XLActionController/releases/tag/5.0.2)
11 |
12 | * Fix incorrect top inset and content offset (#126)
13 | * Support setting cancel view's title color (#129)
14 | * Fix issue introduced with last release that would crash an app when using one of the subspecs
15 |
16 | ### [5.0.1](https://github.com/xmartlabs/XLActionController/releases/tag/5.0.1)
17 |
18 | * Updates for Xcode 11
19 |
20 | ### [5.0.0](https://github.com/xmartlabs/XLActionController/releases/tag/5.0.0)
21 |
22 | * Swift 5.0 source compability.
23 |
24 | ### [4.1.0](https://github.com/xmartlabs/XLActionController/releases/tag/4.1.0)
25 |
26 | * Swift 4.2 source compability.
27 |
28 | ### [4.0.1](https://github.com/xmartlabs/XLActionController/releases/tag/4.0.1)
29 |
30 | * Bug fixes and stability improvements.
31 | * Added support for iphone X.
32 |
33 | ### [4.0.0](https://github.com/xmartlabs/XLActionController/releases/tag/4.0.0)
34 |
35 | * Support for Swift 4.
36 | * Added customizable background color to the Skype action controller, [PR #52](https://github.com/xmartlabs/XLActionController/pull/52)
37 | * Using status bar style from settings in iOS 10, [PR #53](https://github.com/xmartlabs/XLActionController/pull/53)
38 |
39 | ### [3.0.1](https://github.com/xmartlabs/XLActionController/releases/tag/3.0.1)
40 |
41 | * Fixed crash when using ActionCell.xib, [PR #31](https://github.com/xmartlabs/XLActionController/pull/31).
42 |
43 | ### [Swift 3 Support](https://github.com/xmartlabs/XLActionController/releases/tag/3.0.0)
44 |
45 | * Swift 3 and Xcode 8 support, [PR #24](https://github.com/xmartlabs/XLActionController/pull/24)
46 |
47 | ### [2.1.0](https://github.com/xmartlabs/XLActionController/releases/tag/2.1.0)
48 |
49 | * **Breaking change**: `actionTitleLabelConstraintToContainer` and `actionTitleLabelConstraintToImageView` was removed from `ActionCell` class. You must delete these outlets from your xib files, [PR #23](https://github.com/xmartlabs/XLActionController/pull/23).
50 | * **Breaking change**: actions' handlers are now executed after the action controller was completely dismissed, [PR #22](https://github.com/xmartlabs/XLActionController/pull/22).
51 | * Fixed duplicated execution of actions, [PR #22](https://github.com/xmartlabs/XLActionController/pull/22).
52 |
53 | ### [2.0.0](https://github.com/xmartlabs/XLActionController/releases/tag/2.0.0)
54 |
55 | * Bug fixes and stability improvements.
56 | * added support for Xcode 7.3 and swift 2.2.
57 |
58 | ### [1.0.0](https://github.com/xmartlabs/XLActionController/releases/tag/1.0.0)
59 | Released on 2015-12-11. This is the initial version.
60 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contributing Guidelines
2 | --------------------------------------------------
3 |
4 | This document provides general guidelines about how to contribute to the project. Keep in mind these important things before you start contributing.
5 |
6 | ### Asking Questions
7 |
8 | We do not use github issues for general library support. We think this questions should be posted on stack overflow using [XlPagerTabStrip](http://http://stackoverflow.com/questions/tagged/xlactioncontroller) tag.
9 |
10 | ### Reporting issues
11 |
12 | * Use [github issues](https://github.com/xmartlabs/XLActionController/issues) to report a bug.
13 | * Before creating a new issue:
14 | * Make sure you are using the [latest release](https://github.com/xmartlabs/XLActionController/releases).
15 | * Check if the issue was [already reported or fixed](https://github.com/xmartlabs/XLActionController/issues?utf8=%E2%9C%93&q=is%3Aissue). Notice that it may not be released yet.
16 | * If you found a match add a brief comment "I have the same problem" or "+1". This helps prioritize the issues addressing the most common and critical first. If possible add additional information to help us reproduce and fix the issue. Please use your best judgement.
17 | * Reporting issues:
18 | * Please include the following information to help maintainers to fix the problem faster:
19 | * Xcode version you are using.
20 | * iOS version you are targeting.
21 | * Full Xcode console output of stack trace or code compilation error.
22 | * Any other additional detail you think it would be useful to understand and solve the problem.
23 |
24 |
25 | ### Pull requests
26 |
27 | The easiest way to start contributing is searching open issues by `help wanted` tag. We also add a `difficulty` tag (difficulty: easy, difficulty: moderate, difficulty: hard) in order to give an idea of how complex it can be to implement the feature according maintainers project experience.
28 |
29 | * Add test coverage to the feature or fix. We only accept new feature pull requests that have related test coverage. This allows us to keep the library stable as we move forward.
30 | * Remember to document the new feature. We do not accept new feature pull requests without its associated documentation.
31 | * In case of a new feature please update the example project showing the feature.
32 | * Please only one fix or feature per pull request. This will increase the chances your feature will be merged.
33 |
34 |
35 | ###### Suggested git workflow to contribute
36 |
37 | 1. Fork the XLActionController repository.
38 | 2. Clone your forked project into your developer machine: `git clone git@github.com:/XLActionController.git`
39 | 3. Add the original project repo as upstream repository in your forked project: `git remote add upstream git@github.com:xmartlabs/XLActionController.git`
40 | 4. Before starting a new feature make sure your forked master branch is synchronized upstream master branch. Considering you do not mere your pull request into master you can run: `git checkout master` and then `git pull upstream master`. Optionally `git push origin master`.
41 | 5. Create a new branch. Note that the starting point is the upstream master branch HEAD. `git checkout -b my-feature-name`
42 | 6. Stage all your changes `git add .` and commit them `git commit -m "Your commit message"`
43 | 7. Make sure your branch is up to date with upstream master, `git pull --rebase upstream master`, resolve conflicts if necessary. This will move your commit to the top of git stack.
44 | 8. Squash your commits into one commit. `git rebase -i HEAD~6` considering you did 6 commits.
45 | 9. Push your branch into your forked remote repository.
46 | 10. Create a new pull request adding any useful comment.
47 |
48 |
49 | ###### Code style and conventions
50 |
51 | We try to follow our [swift style guide](https://github.com/xmartlabs/Swift-Style-Guide). Following it is not strictly necessary to contribute and to have a pull request accepted but project maintainers try to follow it. We would love to hear your ideas to improve our code style and conventions. Feel free to contribute.
52 |
53 |
54 | ### Feature proposal
55 |
56 | We would love to hear your ideas and make a discussions about it.
57 |
58 | * Use github issues to make feature proposals.
59 | * We use `type: feature request` label to mark all [feature request issues](https://github.com/xmartlabs/XLActionController/labels/type%3A%20feature%20request).
60 | * Before submitting your proposal make sure there is no similar feature request. If you found a match feel free to join the discussion or just add a brief "+1" if you think the feature is worth implementing.
61 | * Be as specific as possible providing a precise explanation of feature request so anyone can understand the problem and the benefits of solving it.
62 |
--------------------------------------------------------------------------------
/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
85 |
91 |
92 |
93 |
94 |
96 |
97 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/Example/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | // AppDelegate.swift
2 | // XLActionController ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 |
27 | @UIApplicationMain
28 | class AppDelegate: UIResponder, UIApplicationDelegate {
29 |
30 | var window: UIWindow?
31 |
32 |
33 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
34 | // Override point for customization after application launch.
35 | return true
36 | }
37 |
38 | func applicationWillResignActive(_ application: UIApplication) {
39 | // 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.
40 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
41 | }
42 |
43 | func applicationDidEnterBackground(_ application: UIApplication) {
44 | // 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.
45 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
46 | }
47 |
48 | func applicationWillEnterForeground(_ application: UIApplication) {
49 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
50 | }
51 |
52 | func applicationDidBecomeActive(_ application: UIApplication) {
53 | // 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.
54 | }
55 |
56 | func applicationWillTerminate(_ application: UIApplication) {
57 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/Example/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "appIcon20pt@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "appIcon20pt@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "appIcon29pt@2x.png",
19 | "scale" : "2x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "appIcon29pt@3x.png",
25 | "scale" : "3x"
26 | },
27 | {
28 | "size" : "40x40",
29 | "idiom" : "iphone",
30 | "filename" : "appIcon40pt@2x.png",
31 | "scale" : "2x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "appIcon40pt@3x.png",
37 | "scale" : "3x"
38 | },
39 | {
40 | "size" : "60x60",
41 | "idiom" : "iphone",
42 | "filename" : "appIcon60pt@2x.png",
43 | "scale" : "2x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "appIcon60pt@3x.png",
49 | "scale" : "3x"
50 | },
51 | {
52 | "idiom" : "ios-marketing",
53 | "size" : "1024x1024",
54 | "scale" : "1x"
55 | }
56 | ],
57 | "info" : {
58 | "version" : 1,
59 | "author" : "xcode"
60 | }
61 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/AppIcon.appiconset/appIcon20pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/AppIcon.appiconset/appIcon20pt@2x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/AppIcon.appiconset/appIcon20pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/AppIcon.appiconset/appIcon20pt@3x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/AppIcon.appiconset/appIcon29pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/AppIcon.appiconset/appIcon29pt@2x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/AppIcon.appiconset/appIcon29pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/AppIcon.appiconset/appIcon29pt@3x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/AppIcon.appiconset/appIcon40pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/AppIcon.appiconset/appIcon40pt@2x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/AppIcon.appiconset/appIcon40pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/AppIcon.appiconset/appIcon40pt@3x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/AppIcon.appiconset/appIcon60pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/AppIcon.appiconset/appIcon60pt@2x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/AppIcon.appiconset/appIcon60pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/AppIcon.appiconset/appIcon60pt@3x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/periscope/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/periscope/pe-background.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "IMG_3582.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/periscope/pe-background.imageset/IMG_3582.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/periscope/pe-background.imageset/IMG_3582.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/skype/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/skype/skype-background.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "skype-background@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/skype/skype-background.imageset/skype-background@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/skype/skype-background.imageset/skype-background@2x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-add-icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "sp-add-icon@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-add-icon.imageset/sp-add-icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/spotify/sp-add-icon.imageset/sp-add-icon@2x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-background.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "IMG_3579.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-background.imageset/IMG_3579.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/spotify/sp-background.imageset/IMG_3579.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-header-icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "sp-header-icon@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-header-icon.imageset/sp-header-icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/spotify/sp-header-icon.imageset/sp-header-icon@2x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-radio-icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "sp-radio-icon@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-radio-icon.imageset/sp-radio-icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/spotify/sp-radio-icon.imageset/sp-radio-icon@2x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-remove-icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "sp-remove-icon@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-remove-icon.imageset/sp-remove-icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/spotify/sp-remove-icon.imageset/sp-remove-icon@2x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-share-icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "sp-share-icon@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-share-icon.imageset/sp-share-icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/spotify/sp-share-icon.imageset/sp-share-icon@2x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-view-album-icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "sp-view-album-icon@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/spotify/sp-view-album-icon.imageset/sp-view-album-icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/spotify/sp-view-album-icon.imageset/sp-view-album-icon@2x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/tweetbot/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/tweetbot/tb-background.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "IMG_3578.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/tweetbot/tb-background.imageset/IMG_3578.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/tweetbot/tb-background.imageset/IMG_3578.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/twitter/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/twitter/tw-background.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "IMG_3577.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/twitter/tw-background.imageset/IMG_3577.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/twitter/tw-background.imageset/IMG_3577.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/twitter/tw-remer.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "tw-remer.jpg",
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/Assets.xcassets/twitter/tw-remer.imageset/tw-remer.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/twitter/tw-remer.imageset/tw-remer.jpg
--------------------------------------------------------------------------------
/Example/Assets.xcassets/twitter/tw-xmartlabs.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "tw-xmartlabs.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/Assets.xcassets/twitter/tw-xmartlabs.imageset/tw-xmartlabs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/twitter/tw-xmartlabs.imageset/tw-xmartlabs.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/xmartlabs/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/xmartlabs/xl_header.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "header.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/xmartlabs/xl_header.imageset/header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/xmartlabs/xl_header.imageset/header.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/xmartlabs/xmartlabs_logo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "xmartlabsLogoCircle@2x.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/Assets.xcassets/xmartlabs/xmartlabs_logo.imageset/xmartlabsLogoCircle@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/xmartlabs/xmartlabs_logo.imageset/xmartlabsLogoCircle@2x.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/youtube/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/youtube/yt-add-to-playlist-icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "yt-add-to-playlist-icon.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/youtube/yt-add-to-playlist-icon.imageset/yt-add-to-playlist-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/youtube/yt-add-to-playlist-icon.imageset/yt-add-to-playlist-icon.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/youtube/yt-add-to-watch-later-icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "yt-add-watch-later-icon.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/youtube/yt-add-to-watch-later-icon.imageset/yt-add-watch-later-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/youtube/yt-add-to-watch-later-icon.imageset/yt-add-watch-later-icon.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/youtube/yt-background.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "IMG_3581.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/youtube/yt-background.imageset/IMG_3581.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/youtube/yt-background.imageset/IMG_3581.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/youtube/yt-cancel-icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "yt-cancel-icon.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/youtube/yt-cancel-icon.imageset/yt-cancel-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/youtube/yt-cancel-icon.imageset/yt-cancel-icon.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/youtube/yt-share-icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "yt-share-icon.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/youtube/yt-share-icon.imageset/yt-share-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Example/Assets.xcassets/youtube/yt-share-icon.imageset/yt-share-icon.png
--------------------------------------------------------------------------------
/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 |
27 |
28 |
--------------------------------------------------------------------------------
/Example/CustomActionControllers/Periscope/Periscope.swift:
--------------------------------------------------------------------------------
1 | // Periscope.swift
2 | // Periscope ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 | #if IMPORT_BASE_XLACTIONCONTROLLER
27 | import XLActionController
28 | #endif
29 |
30 | public class PeriscopeCell: ActionCell {
31 |
32 | public override init(frame: CGRect) {
33 | super.init(frame: frame)
34 | initialize()
35 | }
36 |
37 | required public init?(coder aDecoder: NSCoder) {
38 | super.init(coder: aDecoder)
39 | }
40 |
41 | public override func awakeFromNib() {
42 | super.awakeFromNib()
43 | initialize()
44 | }
45 |
46 | func initialize() {
47 | backgroundColor = .white
48 | let backgroundView = UIView()
49 | backgroundView.backgroundColor = UIColor(white: 0.0, alpha: 0.15)
50 | selectedBackgroundView = backgroundView
51 | separatorView?.backgroundColor = UIColor(red: 224/255.0, green: 224/255.0, blue: 224/255.0, alpha: 1.0)
52 | }
53 | }
54 |
55 |
56 | public class PeriscopeSection: Section {
57 | public override init() {
58 | super.init()
59 | self.data = ()
60 | }
61 | }
62 |
63 | public class PeriscopeHeader: UICollectionReusableView {
64 |
65 | lazy var label: UILabel = {
66 | let label = UILabel()
67 | label.textColor = UIColor(red: 171/255.0, green: 187/255.0, blue: 191/255.0, alpha: 1.0)
68 | label.numberOfLines = 0
69 | label.lineBreakMode = .byWordWrapping
70 | label.font = .systemFont(ofSize: 17.0)
71 | return label
72 | }()
73 |
74 | public override init(frame: CGRect) {
75 | super.init(frame: frame)
76 | backgroundColor = UIColor(white: 0.95, alpha: 1.0)
77 | addSubview(label)
78 | }
79 |
80 | required public init?(coder aDecoder: NSCoder) {
81 | fatalError("init(coder:) has not been implemented")
82 | }
83 | }
84 |
85 | public class PeriscopeActionController: ActionController {
86 |
87 | required public init?(coder aDecoder: NSCoder) {
88 | super.init(coder: aDecoder)
89 | }
90 |
91 | public override init(nibName nibNameOrNil: String? = nil, bundle nibBundleOrNil: Bundle? = nil) {
92 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
93 |
94 | collectionViewLayout.minimumLineSpacing = -0.5
95 | collectionViewLayout.sectionInset = UIEdgeInsets(top: -0.5, left: 0, bottom: 0, right: 0)
96 |
97 | settings.behavior.hideOnScrollDown = false
98 | settings.animation.scale = nil
99 | settings.animation.present.duration = 0.6
100 | settings.animation.dismiss.duration = 0.5
101 | settings.animation.dismiss.options = .curveEaseIn
102 | settings.animation.dismiss.offset = 30
103 |
104 | cellSpec = .nibFile(nibName: "PeriscopeCell", bundle: Bundle(for: PeriscopeCell.self), height: { _ in 60})
105 | sectionHeaderSpec = .cellClass(height: { _ in 5 })
106 | headerSpec = .cellClass(height: { [weak self] (headerData: String) in
107 | guard let me = self else { return 0 }
108 | let label = UILabel(frame: CGRect(x: 0, y: 0, width: me.view.frame.width - 40, height: CGFloat.greatestFiniteMagnitude))
109 | label.numberOfLines = 0
110 | label.font = .systemFont(ofSize: 17.0)
111 | label.text = headerData
112 | label.sizeToFit()
113 | return label.frame.size.height + 20
114 | })
115 |
116 | onConfigureHeader = { [weak self] header, headerData in
117 | guard let me = self else { return }
118 | header.label.frame = CGRect(x: 0, y: 0, width: me.view.frame.size.width - 40, height: CGFloat.greatestFiniteMagnitude)
119 | header.label.text = headerData
120 | header.label.sizeToFit()
121 | header.label.center = CGPoint(x: header.frame.size.width / 2, y:header.frame.size.height / 2)
122 | }
123 | onConfigureSectionHeader = { sectionHeader, sectionHeaderData in
124 | sectionHeader.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
125 | }
126 | onConfigureCellForAction = { [weak self] cell, action, indexPath in
127 | cell.setup(action.data, detail: nil, image: nil)
128 | cell.separatorView?.isHidden = indexPath.item == self!.collectionView.numberOfItems(inSection: indexPath.section) - 1
129 | cell.alpha = action.enabled ? 1.0 : 0.5
130 | cell.actionTitleLabel?.textColor = action.style == .destructive ? UIColor(red: 210/255.0, green: 77/255.0, blue: 56/255.0, alpha: 1.0) : UIColor(red: 0.28, green: 0.64, blue: 0.76, alpha: 1.0)
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/Example/CustomActionControllers/Periscope/PeriscopeCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/Example/CustomActionControllers/Skype/Skype.swift:
--------------------------------------------------------------------------------
1 | // Skype.swift
2 | // Skype ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 | #if IMPORT_BASE_XLACTIONCONTROLLER
27 | import XLActionController
28 | #endif
29 |
30 | open class SkypeCell: UICollectionViewCell {
31 |
32 | @IBOutlet open weak var actionTitleLabel: UILabel!
33 |
34 | public override init(frame: CGRect) {
35 | super.init(frame: frame)
36 | initialize()
37 | }
38 |
39 | required public init?(coder aDecoder: NSCoder) {
40 | super.init(coder: aDecoder)
41 | }
42 |
43 | open override func awakeFromNib() {
44 | super.awakeFromNib()
45 | initialize()
46 | }
47 |
48 | func initialize() {
49 | backgroundColor = .clear
50 | actionTitleLabel?.textColor = .darkGray
51 | let backgroundView = UIView()
52 | backgroundView.backgroundColor = backgroundColor
53 | selectedBackgroundView = backgroundView
54 | }
55 | }
56 |
57 |
58 | open class SkypeActionController: ActionController {
59 |
60 | static let bottomPadding: CGFloat = 20.0
61 |
62 | open var backgroundColor: UIColor = UIColor(red: 18/255.0, green: 165/255.0, blue: 244/255.0, alpha: 1.0)
63 |
64 | fileprivate var contextView: ContextView!
65 | fileprivate var normalAnimationRect: UIView!
66 | fileprivate var springAnimationRect: UIView!
67 |
68 | let topSpace = CGFloat(40)
69 |
70 | public override init(nibName nibNameOrNil: String? = nil, bundle nibBundleOrNil: Bundle? = nil) {
71 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
72 |
73 | cellSpec = .nibFile(nibName: "SkypeCell", bundle: Bundle(for: SkypeCell.self), height: { _ in 60 })
74 | settings.animation.scale = nil
75 | settings.animation.present.duration = 0.5
76 | settings.animation.present.options = [.curveEaseOut, .allowUserInteraction]
77 | settings.animation.present.springVelocity = 0.0
78 | settings.animation.present.damping = 0.7
79 | settings.statusBar.style = .default
80 |
81 | onConfigureCellForAction = { cell, action, indexPath in
82 | cell.actionTitleLabel.text = action.data
83 | cell.actionTitleLabel.textColor = .white
84 | cell.alpha = action.enabled ? 1.0 : 0.5
85 | }
86 | }
87 |
88 | required public init?(coder aDecoder: NSCoder) {
89 | super.init(coder: aDecoder)
90 | }
91 |
92 | open override func viewDidLoad() {
93 | super.viewDidLoad()
94 |
95 | let width = collectionView.bounds.width - safeAreaInsets.left - safeAreaInsets.right
96 | let height = contentHeight + topSpace + SkypeActionController.bottomPadding + safeAreaInsets.bottom
97 | contextView = ContextView(frame: CGRect(x: 0, y: -topSpace, width: width, height: height))
98 | contextView.animatedBackgroundColor = backgroundColor;
99 | contextView.autoresizingMask = [.flexibleWidth, .flexibleBottomMargin]
100 |
101 | collectionView.clipsToBounds = false
102 | collectionView.addSubview(contextView)
103 | collectionView.sendSubviewToBack(contextView)
104 |
105 | normalAnimationRect = UIView(frame: CGRect(x: 0, y: view.bounds.height / 2, width: 30, height: 30))
106 | normalAnimationRect.isHidden = true
107 | view.addSubview(normalAnimationRect)
108 |
109 | springAnimationRect = UIView(frame: CGRect(x: 40, y: view.bounds.height / 2, width: 30, height: 30))
110 | springAnimationRect.isHidden = true
111 | view.addSubview(springAnimationRect)
112 |
113 | backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.65)
114 | }
115 |
116 | @available(iOS 11, *)
117 | override open func viewSafeAreaInsetsDidChange() {
118 | super.viewSafeAreaInsetsDidChange()
119 | contextView.frame.size.height = contentHeight + topSpace + SkypeActionController.bottomPadding + safeAreaInsets.bottom
120 | contextView.frame.size.width = collectionView.bounds.width - safeAreaInsets.left - safeAreaInsets.right
121 | }
122 |
123 | override open func onWillPresentView() {
124 | super.onWillPresentView()
125 |
126 | collectionView.frame.origin.y = contentHeight + (topSpace - contextView.topSpace)
127 |
128 | startAnimation()
129 | let initSpace = CGFloat(45.0)
130 | let initTime = 0.1
131 | let animationDuration = settings.animation.present.duration - 0.1
132 |
133 | let options: UIView.AnimationOptions = [.curveEaseOut, .allowUserInteraction]
134 | UIView.animate(withDuration: initTime, delay: settings.animation.present.delay, options: options, animations: { [weak self] in
135 | guard let me = self else {
136 | return
137 | }
138 |
139 | var frame = me.springAnimationRect.frame
140 | frame.origin.y = frame.origin.y - initSpace
141 | me.springAnimationRect.frame = frame
142 | }, completion: { [weak self] finished in
143 | guard let me = self , finished else {
144 | self?.finishAnimation()
145 | return
146 | }
147 |
148 | UIView.animate(withDuration: animationDuration - initTime, delay: 0, options: options, animations: { [weak self] in
149 | guard let me = self else {
150 | return
151 | }
152 |
153 | var frame = me.springAnimationRect.frame
154 | frame.origin.y -= (me.contentHeight - initSpace)
155 | me.springAnimationRect.frame = frame
156 | }, completion: { (finish) -> Void in
157 | me.finishAnimation()
158 | })
159 | })
160 |
161 |
162 | UIView.animate(withDuration: animationDuration - initTime, delay: settings.animation.present.delay + initTime, options: options, animations: { [weak self] in
163 | guard let me = self else {
164 | return
165 | }
166 |
167 | var frame = me.normalAnimationRect.frame
168 | frame.origin.y -= me.contentHeight
169 | me.normalAnimationRect.frame = frame
170 | }, completion:nil)
171 | }
172 |
173 |
174 | override open func dismissView(_ presentedView: UIView, presentingView: UIView, animationDuration: Double, completion: ((_ completed: Bool) -> Void)?) {
175 | finishAnimation()
176 | finishAnimation()
177 |
178 | let animationSettings = settings.animation.dismiss
179 | UIView.animate(withDuration: animationDuration,
180 | delay: animationSettings.delay,
181 | usingSpringWithDamping: animationSettings.damping,
182 | initialSpringVelocity: animationSettings.springVelocity,
183 | options: animationSettings.options,
184 | animations: { [weak self] in
185 | self?.backgroundView.alpha = 0.0
186 | },
187 | completion:nil)
188 |
189 | gravityBehavior.action = { [weak self] in
190 | if let me = self {
191 | let progress = min(1.0, me.collectionView.frame.origin.y / (me.contentHeight + (me.topSpace - me.contextView.topSpace)))
192 | let pixels = min(20, progress * 150.0)
193 | me.contextView.diff = -pixels
194 | me.contextView.setNeedsDisplay()
195 |
196 | if me.collectionView.frame.origin.y > me.view.bounds.size.height {
197 | self?.animator.removeAllBehaviors()
198 | completion?(true)
199 | }
200 | }
201 | }
202 | animator.addBehavior(gravityBehavior)
203 | }
204 |
205 | // MARK: - Private Helpers
206 |
207 | fileprivate var diff = CGFloat(0)
208 | fileprivate var displayLink: CADisplayLink!
209 | fileprivate var animationCount = 0
210 |
211 | fileprivate lazy var animator: UIDynamicAnimator = { [unowned self] in
212 | let animator = UIDynamicAnimator(referenceView: self.view)
213 | return animator
214 | }()
215 |
216 | fileprivate lazy var gravityBehavior: UIGravityBehavior = { [unowned self] in
217 | let gravityBehavior = UIGravityBehavior(items: [self.collectionView])
218 | gravityBehavior.magnitude = 2.0
219 | return gravityBehavior
220 | }()
221 |
222 | @objc fileprivate func update(_ displayLink: CADisplayLink) {
223 | let normalRectLayer = normalAnimationRect.layer.presentation()
224 | let springRectLayer = springAnimationRect.layer.presentation()
225 |
226 | guard let normalRectFrame = normalRectLayer?.frame,
227 | let springRectFrame = springRectLayer?.frame else {
228 | return
229 | }
230 | contextView.diff = normalRectFrame.origin.y - springRectFrame.origin.y
231 | contextView.setNeedsDisplay()
232 | }
233 |
234 | fileprivate func startAnimation() {
235 | if displayLink == nil {
236 | self.displayLink = CADisplayLink(target: self, selector: #selector(SkypeActionController.update(_:)))
237 | self.displayLink.add(to: RunLoop.main, forMode: RunLoop.Mode.default)
238 | }
239 | animationCount += 1
240 | }
241 |
242 | fileprivate func finishAnimation() {
243 | animationCount -= 1
244 | if animationCount == 0 {
245 | displayLink.invalidate()
246 | displayLink = nil
247 | }
248 | }
249 |
250 | fileprivate class ContextView: UIView {
251 | let topSpace = CGFloat(25)
252 | var diff = CGFloat(0)
253 | var animatedBackgroundColor: UIColor!
254 |
255 | override init(frame: CGRect) {
256 | super.init(frame: frame)
257 | backgroundColor = .clear
258 | }
259 |
260 | required init?(coder aDecoder: NSCoder) {
261 | fatalError("init(coder:) has not been implemented")
262 | }
263 |
264 | override func draw(_ rect: CGRect) {
265 | let path = UIBezierPath()
266 |
267 | path.move(to: CGPoint(x: 0, y: frame.height))
268 | path.addLine(to: CGPoint(x: frame.width, y: frame.height))
269 | path.addLine(to: CGPoint(x: frame.width, y: topSpace))
270 | path.addQuadCurve(to: CGPoint(x: 0, y: topSpace), controlPoint: CGPoint(x: frame.width/2, y: topSpace - diff))
271 | path.close()
272 |
273 | guard let context = UIGraphicsGetCurrentContext() else {
274 | return
275 | }
276 | context.addPath(path.cgPath)
277 | animatedBackgroundColor.set()
278 | context.fillPath()
279 | }
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/Example/CustomActionControllers/Skype/SkypeCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Example/CustomActionControllers/Spotify/Spotify.swift:
--------------------------------------------------------------------------------
1 | // Spotify.swift
2 | // Spotify ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 | #if IMPORT_BASE_XLACTIONCONTROLLER
27 | import XLActionController
28 | #endif
29 |
30 | open class SpotifyCell: ActionCell {
31 |
32 | public override init(frame: CGRect) {
33 | super.init(frame: frame)
34 | initialize()
35 | }
36 |
37 | required public init?(coder aDecoder: NSCoder) {
38 | super.init(coder: aDecoder)
39 | }
40 |
41 | open override func awakeFromNib() {
42 | super.awakeFromNib()
43 | initialize()
44 | }
45 |
46 | func initialize() {
47 | backgroundColor = .clear
48 | let backgroundView = UIView()
49 | backgroundView.backgroundColor = UIColor.white.withAlphaComponent(0.3)
50 | selectedBackgroundView = backgroundView
51 | actionTitleLabel?.textColor = .white
52 | actionTitleLabel?.textAlignment = .left
53 |
54 | }
55 | }
56 |
57 | public struct SpotifyHeaderData {
58 |
59 | var title: String
60 | var subtitle: String
61 | var image: UIImage
62 |
63 | public init(title: String, subtitle: String, image: UIImage) {
64 | self.title = title
65 | self.subtitle = subtitle
66 | self.image = image
67 | }
68 | }
69 |
70 | open class SpotifyHeaderView: UICollectionReusableView {
71 |
72 | open lazy var imageView: UIImageView = {
73 | let imageView = UIImageView(frame: CGRect.zero)
74 | imageView.image = UIImage(named: "sp-header-icon")
75 | imageView.translatesAutoresizingMaskIntoConstraints = false
76 | return imageView
77 | }()
78 |
79 | open lazy var title: UILabel = {
80 | let title = UILabel(frame: CGRect.zero)
81 | title.font = UIFont(name: "HelveticaNeue-Bold", size: 18)
82 | title.text = "The Fast And ... The Furious Soundtrack Collection"
83 | title.textColor = UIColor.white
84 | title.translatesAutoresizingMaskIntoConstraints = false
85 | title.sizeToFit()
86 | return title
87 | }()
88 |
89 | open lazy var artist: UILabel = {
90 | let discArtist = UILabel(frame: CGRect.zero)
91 | discArtist.font = UIFont(name: "HelveticaNeue", size: 16)
92 | discArtist.text = "Various..."
93 | discArtist.textColor = UIColor.white.withAlphaComponent(0.8)
94 | discArtist.translatesAutoresizingMaskIntoConstraints = false
95 | discArtist.sizeToFit()
96 | return discArtist
97 | }()
98 |
99 | public override init(frame: CGRect) {
100 | super.init(frame: frame)
101 | initialize()
102 | }
103 |
104 | required public init?(coder aDecoder: NSCoder) {
105 | super.init(coder: aDecoder)
106 | }
107 |
108 | open override func awakeFromNib() {
109 | super.awakeFromNib()
110 | initialize()
111 | }
112 |
113 | func initialize() {
114 | translatesAutoresizingMaskIntoConstraints = false
115 | backgroundColor = .clear
116 | addSubview(imageView)
117 | addSubview(title)
118 | addSubview(artist)
119 | let separator: UIView = {
120 | let separator = UIView(frame: CGRect.zero)
121 | separator.backgroundColor = UIColor.white.withAlphaComponent(0.3)
122 | separator.translatesAutoresizingMaskIntoConstraints = false
123 | return separator
124 | }()
125 | addSubview(separator)
126 |
127 | let views = [ "ico": imageView, "title": title, "artist": artist, "separator": separator ]
128 | let metrics = [ "icow": 54, "icoh": 54 ]
129 | let options = NSLayoutConstraint.FormatOptions()
130 |
131 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-15-[ico(icow)]-10-[title]-15-|", options: options, metrics: metrics, views: views))
132 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[separator]|", options: options, metrics: metrics, views: views))
133 |
134 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[ico(icoh)]", options: options, metrics: metrics, views: views))
135 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-18-[title][artist]", options: .alignAllLeft, metrics: metrics, views: views))
136 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[separator(1)]|", options: options, metrics: metrics, views: views))
137 | }
138 | }
139 |
140 | open class SpotifyActionController: ActionController {
141 |
142 | fileprivate lazy var blurView: UIVisualEffectView = {
143 | let blurView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
144 | blurView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
145 | return blurView
146 | }()
147 |
148 | open override func viewDidLoad() {
149 | super.viewDidLoad()
150 | backgroundView.addSubview(blurView)
151 |
152 | cancelView?.frame.origin.y = view.bounds.size.height // Starts hidden below screen
153 | cancelView?.layer.shadowColor = UIColor.black.cgColor
154 | cancelView?.layer.shadowOffset = CGSize( width: 0, height: -4)
155 | cancelView?.layer.shadowRadius = 2
156 | cancelView?.layer.shadowOpacity = 0.8
157 | }
158 |
159 | open override func viewWillAppear(_ animated: Bool) {
160 | super.viewWillAppear(animated)
161 | blurView.frame = backgroundView.bounds
162 | }
163 |
164 | public override init(nibName nibNameOrNil: String? = nil, bundle nibBundleOrNil: Bundle? = nil) {
165 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
166 | settings.behavior.bounces = true
167 | settings.behavior.scrollEnabled = true
168 | settings.cancelView.showCancel = true
169 | settings.animation.scale = nil
170 | settings.animation.present.springVelocity = 0.0
171 | settings.cancelView.hideCollectionViewBehindCancelView = true
172 |
173 | cellSpec = .nibFile(nibName: "SpotifyCell", bundle: Bundle(for: SpotifyCell.self), height: { _ in 60 })
174 | headerSpec = .cellClass( height: { _ in 84 })
175 |
176 | onConfigureCellForAction = { [weak self] cell, action, indexPath in
177 | cell.setup(action.data?.title, detail: action.data?.subtitle, image: action.data?.image)
178 | cell.separatorView?.isHidden = indexPath.item == (self?.collectionView.numberOfItems(inSection: indexPath.section))! - 1
179 | cell.alpha = action.enabled ? 1.0 : 0.5
180 | }
181 | onConfigureHeader = { (header: SpotifyHeaderView, data: SpotifyHeaderData) in
182 | header.title.text = data.title
183 | header.artist.text = data.subtitle
184 | header.imageView.image = data.image
185 | }
186 | }
187 |
188 | required public init?(coder aDecoder: NSCoder) {
189 | super.init(coder: aDecoder)
190 | }
191 |
192 | open override func performCustomDismissingAnimation(_ presentedView: UIView, presentingView: UIView) {
193 | super.performCustomDismissingAnimation(presentedView, presentingView: presentingView)
194 | cancelView?.frame.origin.y = view.bounds.size.height + 10
195 | }
196 |
197 | open override func onWillPresentView() {
198 | cancelView?.frame.origin.y = view.bounds.size.height
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/Example/CustomActionControllers/Spotify/SpotifyCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | HelveticaNeue
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/Example/CustomActionControllers/Tweetbot/Tweetbot.swift:
--------------------------------------------------------------------------------
1 | // Tweetbot.swift
2 | // Tweetbot ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 | #if IMPORT_BASE_XLACTIONCONTROLLER
27 | import XLActionController
28 | #endif
29 |
30 | open class TweetbotCell: ActionCell {
31 |
32 | public override init(frame: CGRect) {
33 | super.init(frame: frame)
34 | initialize()
35 | }
36 |
37 | required public init?(coder aDecoder: NSCoder) {
38 | super.init(coder: aDecoder)
39 | }
40 |
41 | open override func awakeFromNib() {
42 | super.awakeFromNib()
43 | initialize()
44 | }
45 |
46 | func initialize() {
47 | actionTitleLabel?.font = UIFont(name: "HelveticaNeue-Bold", size: 18)
48 | actionTitleLabel?.textColor = .white
49 | actionTitleLabel?.textAlignment = .center
50 | backgroundColor = .darkGray
51 | let backgroundView = UIView()
52 | backgroundView.backgroundColor = UIColor(red: 0.31, green: 0.42, blue: 0.54, alpha: 1.0)
53 | selectedBackgroundView = backgroundView
54 | }
55 | }
56 |
57 | open class TweetbotActionController: DynamicsActionController {
58 |
59 | public override init(nibName nibNameOrNil: String? = nil, bundle nibBundleOrNil: Bundle? = nil) {
60 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
61 | backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
62 | settings.animation.present.duration = 0.5
63 | settings.animation.dismiss.duration = 0.5
64 | settings.behavior.bounces = true
65 | settings.behavior.useDynamics = true
66 | collectionView.contentInset = UIEdgeInsets(top: 0.0, left: 12.0, bottom: 6.0, right: 12.0)
67 |
68 | cellSpec = .nibFile(nibName: "TweetbotCell", bundle: Bundle(for: TweetbotCell.self), height: { _ in 50 })
69 |
70 | onConfigureCellForAction = { [weak self] cell, action, indexPath in
71 |
72 | cell.setup(action.data, detail: nil, image: nil)
73 | let actions = self?.sectionForIndex(indexPath.section)?.actions
74 | let actionsCount = actions!.count
75 | cell.separatorView?.isHidden = indexPath.item == (self?.collectionView.numberOfItems(inSection: indexPath.section))! - 1
76 | cell.backgroundColor = action.style == .cancel ? UIColor(white: 0.23, alpha: 1.0) : .darkGray
77 | cell.alpha = action.enabled ? 1.0 : 0.5
78 |
79 | var corners = UIRectCorner()
80 | if indexPath.item == 0 {
81 | corners = [.topLeft, .topRight]
82 | }
83 | if indexPath.item == actionsCount - 1 {
84 | corners = corners.union([.bottomLeft, .bottomRight])
85 | }
86 |
87 | if corners == .allCorners {
88 | cell.layer.mask = nil
89 | cell.layer.cornerRadius = 8.0
90 | } else {
91 | let borderMask = CAShapeLayer()
92 | borderMask.frame = cell.bounds
93 | borderMask.path = UIBezierPath(roundedRect: cell.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: 8.0, height: 8.0)).cgPath
94 | cell.layer.mask = borderMask
95 | }
96 | }
97 | }
98 |
99 | required public init?(coder aDecoder: NSCoder) {
100 | super.init(coder: aDecoder)
101 | }
102 |
103 | // MARK: - UICollectionViewDelegateFlowLayout
104 |
105 | open override func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
106 | return UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 0.0)
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/Example/CustomActionControllers/Tweetbot/TweetbotCell.xib:
--------------------------------------------------------------------------------
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 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/Example/CustomActionControllers/Twitter/Twitter.swift:
--------------------------------------------------------------------------------
1 | // Twitter.swift
2 | // Twitter ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 | #if IMPORT_BASE_XLACTIONCONTROLLER
27 | import XLActionController
28 | #endif
29 |
30 | open class TwitterCell: ActionCell {
31 |
32 | public override init(frame: CGRect) {
33 | super.init(frame: frame)
34 | initialize()
35 | }
36 |
37 | required public init?(coder aDecoder: NSCoder) {
38 | super.init(coder: aDecoder)
39 | }
40 |
41 | open override func awakeFromNib() {
42 | super.awakeFromNib()
43 | initialize()
44 | }
45 |
46 | func initialize() {
47 | backgroundColor = .white
48 | actionImageView?.clipsToBounds = true
49 | actionImageView?.layer.cornerRadius = 5.0
50 | let backgroundView = UIView()
51 | backgroundView.backgroundColor = UIColor(white: 0.0, alpha: 0.15)
52 | selectedBackgroundView = backgroundView
53 | }
54 | }
55 |
56 | open class TwitterActionControllerHeader: UICollectionReusableView {
57 |
58 | lazy var label: UILabel = {
59 | let label = UILabel()
60 | label.translatesAutoresizingMaskIntoConstraints = false
61 | label.textAlignment = .center
62 | label.backgroundColor = .white
63 | label.font = UIFont.boldSystemFont(ofSize: 17)
64 | return label
65 | }()
66 |
67 | lazy var bottomLine: UIView = {
68 | let bottomLine = UIView()
69 | bottomLine.translatesAutoresizingMaskIntoConstraints = false
70 | bottomLine.backgroundColor = .lightGray
71 | return bottomLine
72 | }()
73 |
74 | override init(frame: CGRect) {
75 | super.init(frame: frame)
76 | backgroundColor = .white
77 | addSubview(label)
78 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[label]|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["label": label]))
79 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[label]|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["label": label]))
80 | addSubview(bottomLine)
81 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[line(1)]|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["line": bottomLine]))
82 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[line]|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["line": bottomLine]))
83 | }
84 |
85 | required public init?(coder aDecoder: NSCoder) {
86 | super.init(coder: aDecoder)
87 | }
88 | }
89 |
90 |
91 | open class TwitterActionController: ActionController {
92 |
93 | static let bottomPadding: CGFloat = 20.0
94 |
95 | lazy var hideBottomSpaceView: UIView = {
96 | let width = collectionView.bounds.width - safeAreaInsets.left - safeAreaInsets.right
97 | let height = contentHeight + TwitterActionController.bottomPadding + safeAreaInsets.bottom
98 | let hideBottomSpaceView = UIView(frame: CGRect.init(x: 0, y: 0, width: width, height: height))
99 | hideBottomSpaceView.autoresizingMask = [.flexibleWidth, .flexibleBottomMargin]
100 | hideBottomSpaceView.backgroundColor = .white
101 | return hideBottomSpaceView
102 | }()
103 |
104 | public override init(nibName nibNameOrNil: String? = nil, bundle nibBundleOrNil: Bundle? = nil) {
105 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
106 | settings.animation.present.duration = 0.6
107 | settings.animation.dismiss.duration = 0.6
108 | cellSpec = CellSpec.nibFile(nibName: "TwitterCell", bundle: Bundle(for: TwitterCell.self), height: { _ in 56 })
109 | headerSpec = .cellClass(height: { _ -> CGFloat in return 45 })
110 |
111 | onConfigureHeader = { header, title in
112 | header.label.text = title
113 | }
114 | onConfigureCellForAction = { [weak self] cell, action, indexPath in
115 | cell.setup(action.data?.title, detail: action.data?.subtitle, image: action.data?.image)
116 | cell.separatorView?.isHidden = indexPath.item == (self?.collectionView.numberOfItems(inSection: indexPath.section))! - 1
117 | cell.alpha = action.enabled ? 1.0 : 0.5
118 | }
119 | }
120 |
121 | required public init?(coder aDecoder: NSCoder) {
122 | fatalError("init(coder:) has not been implemented")
123 | }
124 |
125 | open override func viewDidLoad() {
126 | super.viewDidLoad()
127 |
128 | collectionView.clipsToBounds = false
129 | collectionView.addSubview(hideBottomSpaceView)
130 | collectionView.sendSubviewToBack(hideBottomSpaceView)
131 | }
132 |
133 | @available(iOS 11, *)
134 | override open func viewSafeAreaInsetsDidChange() {
135 | super.viewSafeAreaInsetsDidChange()
136 | hideBottomSpaceView.frame.size.height = contentHeight + TwitterActionController.bottomPadding + safeAreaInsets.bottom
137 | hideBottomSpaceView.frame.size.width = collectionView.bounds.width - safeAreaInsets.left - safeAreaInsets.right
138 | }
139 |
140 | override open func dismissView(_ presentedView: UIView, presentingView: UIView, animationDuration: Double, completion: ((_ completed: Bool) -> Void)?) {
141 | onWillDismissView()
142 | let animationSettings = settings.animation.dismiss
143 | let upTime = 0.1
144 | UIView.animate(withDuration: upTime, delay: 0, options: .curveEaseIn, animations: { [weak self] in
145 | self?.collectionView.frame.origin.y -= 10
146 | }, completion: { [weak self] (completed) -> Void in
147 | UIView.animate(withDuration: animationDuration - upTime,
148 | delay: 0,
149 | usingSpringWithDamping: animationSettings.damping,
150 | initialSpringVelocity: animationSettings.springVelocity,
151 | options: UIView.AnimationOptions.curveEaseIn,
152 | animations: { [weak self] in
153 | presentingView.transform = CGAffineTransform.identity
154 | self?.performCustomDismissingAnimation(presentedView, presentingView: presentingView)
155 | },
156 | completion: { [weak self] finished in
157 | self?.onDidDismissView()
158 | completion?(finished)
159 | })
160 | })
161 | }
162 | }
163 |
164 |
--------------------------------------------------------------------------------
/Example/CustomActionControllers/Twitter/TwitterCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
39 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/Example/CustomActionControllers/Youtube/Youtube.swift:
--------------------------------------------------------------------------------
1 | // Youtube.swift
2 | // Youtube ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 | #if IMPORT_BASE_XLACTIONCONTROLLER
27 | import XLActionController
28 | #endif
29 |
30 | open class YoutubeCell: ActionCell {
31 |
32 | open lazy var animatableBackgroundView: UIView = { [weak self] in
33 | let view = UIView(frame: self?.frame ?? CGRect.zero)
34 | view.backgroundColor = UIColor.red.withAlphaComponent(0.40)
35 | return view
36 | }()
37 |
38 | public override init(frame: CGRect) {
39 | super.init(frame: frame)
40 | initialize()
41 | }
42 |
43 | required public init?(coder aDecoder: NSCoder) {
44 | super.init(coder: aDecoder)
45 | }
46 |
47 | open override func awakeFromNib() {
48 | super.awakeFromNib()
49 | initialize()
50 | }
51 |
52 | func initialize() {
53 | actionTitleLabel?.textColor = UIColor(white: 0.098, alpha: 1.0)
54 | let backgroundView = UIView()
55 | backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.0)
56 | backgroundView.addSubview(animatableBackgroundView)
57 | selectedBackgroundView = backgroundView
58 | }
59 |
60 | open override var isHighlighted: Bool {
61 | didSet {
62 | if isHighlighted {
63 | animatableBackgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.0)
64 | animatableBackgroundView.frame = CGRect(x: 0, y: 0, width: 30, height: frame.height)
65 | animatableBackgroundView.center = CGPoint(x: frame.width * 0.5, y: frame.height * 0.5)
66 |
67 | UIView.animate(withDuration: 0.5) { [weak self] in
68 | guard let me = self else {
69 | return
70 | }
71 |
72 | me.animatableBackgroundView.frame = CGRect(x: 0, y: 0, width: me.frame.width, height: me.frame.height)
73 | me.animatableBackgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.08)
74 | }
75 | } else {
76 | animatableBackgroundView.backgroundColor = animatableBackgroundView.backgroundColor?.withAlphaComponent(0.0)
77 | }
78 | }
79 | }
80 | }
81 |
82 | open class YoutubeActionController: ActionController {
83 |
84 | public override init(nibName nibNameOrNil: String? = nil, bundle nibBundleOrNil: Bundle? = nil) {
85 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
86 |
87 | collectionViewLayout.minimumLineSpacing = -0.5
88 |
89 | settings.behavior.hideOnScrollDown = false
90 | settings.animation.scale = nil
91 | settings.animation.present.duration = 0.6
92 | settings.animation.dismiss.duration = 0.6
93 | settings.animation.dismiss.offset = 30
94 | settings.animation.dismiss.options = .curveLinear
95 |
96 | cellSpec = .nibFile(nibName: "YoutubeCell", bundle: Bundle(for: YoutubeCell.self), height: { _ in 46 })
97 |
98 | onConfigureCellForAction = { cell, action, indexPath in
99 | cell.setup(action.data?.title, detail: action.data?.subtitle, image: action.data?.image)
100 | cell.alpha = action.enabled ? 1.0 : 0.5
101 | }
102 | }
103 |
104 | required public init?(coder aDecoder: NSCoder) {
105 | fatalError("init(coder:) has not been implemented")
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/Example/CustomActionControllers/Youtube/YoutubeCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/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 | XLActionController
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 5.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/Example/MainViewController.swift:
--------------------------------------------------------------------------------
1 | // MainViewController.swift
2 | // MainViewController ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 |
27 | class MainViewController: UITableViewController {
28 |
29 | override func viewDidLoad() {
30 | super.viewDidLoad()
31 |
32 | navigationItem.title = "XLActionController's Examples"
33 | }
34 |
35 | override func viewWillAppear(_ animated: Bool) {
36 | super.viewWillAppear(animated)
37 | navigationController?.setNavigationBarHidden(false, animated: animated)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Example/PeriscopeExampleViewController.swift:
--------------------------------------------------------------------------------
1 | // PeriscopeExampleViewController.swift
2 | // XLActionController ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 | import XLActionController
27 |
28 | class PeriscopeExampleViewController: UIViewController {
29 |
30 | override func viewWillAppear(_ animated: Bool) {
31 | super.viewWillAppear(animated)
32 | navigationController?.setNavigationBarHidden(true, animated: animated)
33 | }
34 |
35 | override var preferredStatusBarStyle : UIStatusBarStyle {
36 | return .lightContent
37 | }
38 |
39 | @IBAction func backButtonDidTouch(_ sender: UIButton) {
40 | _ = self.navigationController?.popViewController(animated: true)
41 | }
42 |
43 | @IBAction func tapGestureDidRecognize(_ sender: UITapGestureRecognizer) {
44 | let actionController = PeriscopeActionController()
45 | actionController.headerData = "Are you sure you want to block?"
46 | actionController.addAction(Action("Block user", style: .destructive, handler: { action in
47 | }))
48 | actionController.addSection(PeriscopeSection())
49 | actionController.addAction(Action("Cancel", style: .cancel, handler: { action in
50 | }))
51 | present(actionController, animated: true, completion: nil)
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Example/SkypeExampleViewController.swift:
--------------------------------------------------------------------------------
1 | // SkypeExampleViewController.swift
2 | // XLActionController ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 | import XLActionController
27 |
28 | class SkypeExampleViewController: UIViewController {
29 |
30 | override func viewWillAppear(_ animated: Bool) {
31 | super.viewWillAppear(animated)
32 | navigationController?.setNavigationBarHidden(true, animated: animated)
33 | }
34 |
35 | @IBAction func backButtonDidTouch(_ sender: UIButton) {
36 | _ = navigationController?.popViewController(animated: true)
37 | }
38 |
39 | @IBAction func tapGestureDidRecognize(_ sender: UITapGestureRecognizer) {
40 | let actionController = SkypeActionController()
41 | actionController.addAction(Action("Take photo", style: .default, handler: { action in
42 | }))
43 | actionController.addAction(Action("Choose existing photo", style: .default, handler: { action in
44 | }))
45 | actionController.addAction(Action("Remove profile picture", style: .default, handler: { action in
46 | }))
47 | actionController.addAction(Action("Cancel", style: .cancel, handler: nil))
48 |
49 | present(actionController, animated: true, completion: nil)
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/Example/SpotifyExampleViewController.swift:
--------------------------------------------------------------------------------
1 | // SpotifyExampleViewController.swift
2 | // XLActionController ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 | import XLActionController
27 |
28 | class SpotifyExampleViewController: UIViewController {
29 |
30 | override func viewWillAppear(_ animated: Bool) {
31 | super.viewWillAppear(animated)
32 | navigationController?.setNavigationBarHidden(true, animated: animated)
33 | }
34 |
35 | override func viewDidLoad() {
36 | navigationController?.setNavigationBarHidden(true, animated: false)
37 | }
38 |
39 | override var preferredStatusBarStyle : UIStatusBarStyle {
40 | return .lightContent
41 | }
42 |
43 | @IBAction func backButtonDidTouch(_ sender: UIButton) {
44 | _ = navigationController?.popViewController(animated: true)
45 | }
46 |
47 | @IBAction func tapGestureDidRecognize(_ sender: UITapGestureRecognizer) {
48 | let actionController = SpotifyActionController()
49 | actionController.headerData = SpotifyHeaderData(title: "The Fast And The Furious Soundtrack Collection", subtitle: "Various Artists", image: UIImage(named: "sp-header-icon")!)
50 | actionController.addAction(Action(ActionData(title: "Save Full Album", image: UIImage(named: "sp-add-icon")!), style: .default, handler: { action in }))
51 | actionController.addAction(Action(ActionData(title: "Remove", image: UIImage(named: "sp-remove-icon")!), style: .default, handler: { action in }))
52 | actionController.addAction(Action(ActionData(title: "Share", image: UIImage(named: "sp-share-icon")!), style: .default, handler: { action in }))
53 | actionController.addAction(Action(ActionData(title: "Go to Album", image: UIImage(named: "sp-view-album-icon")!), style: .default, handler: { action in }))
54 | actionController.addAction(Action(ActionData(title: "Start radio", image: UIImage(named: "sp-radio-icon")!), style: .default, handler: { action in }))
55 |
56 |
57 | present(actionController, animated: true, completion: nil)
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Example/TweetbotExampleViewController.swift:
--------------------------------------------------------------------------------
1 | // TweetBotExampleViewController.swift
2 | // XLActionController ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 | import XLActionController
27 |
28 | class TweetBotExampleViewController: UIViewController {
29 |
30 | override func viewWillAppear(_ animated: Bool) {
31 | super.viewWillAppear(animated)
32 | navigationController?.setNavigationBarHidden(true, animated: animated)
33 | }
34 |
35 | override var preferredStatusBarStyle : UIStatusBarStyle {
36 | return .lightContent
37 | }
38 |
39 | @IBAction func backButtonDidTouch(_ sender: UIButton) {
40 | _ = navigationController?.popViewController(animated: true)
41 | }
42 |
43 | @IBAction func tapGestureDidRecognize(_ sender: UITapGestureRecognizer) {
44 | let actionController = TweetbotActionController()
45 |
46 | actionController.addAction(Action("View Details", style: .default, handler: { action in
47 | }))
48 | actionController.addAction(Action("View Retweets", style: .default, handler: { action in
49 | }))
50 | actionController.addAction(Action("View in Favstar", style: .default, handler: { action in
51 | }))
52 | actionController.addAction(Action("Translate", style: .default, executeImmediatelyOnTouch: true, handler: { action in
53 | }))
54 | actionController.addSection(Section())
55 | actionController.addAction(Action("Cancel", style: .cancel, handler:nil))
56 |
57 | present(actionController, animated: true, completion: nil)
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/Example/TwitterExampleViewController.swift:
--------------------------------------------------------------------------------
1 | // TwitterExampleViewController.swift
2 | // XLActionController ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 | import XLActionController
27 |
28 | class TwitterExampleViewController: UIViewController {
29 |
30 | override func viewWillAppear(_ animated: Bool) {
31 | super.viewWillAppear(animated)
32 | navigationController?.setNavigationBarHidden(true, animated: animated)
33 | }
34 |
35 | override var preferredStatusBarStyle : UIStatusBarStyle {
36 | return .lightContent
37 | }
38 |
39 | @IBAction func backButtonDidTouch(_ sender: UIButton) {
40 | _ = navigationController?.popViewController(animated: true)
41 | }
42 |
43 | @IBAction func tapGestureDidRecognize(_ sender: UITapGestureRecognizer) {
44 | let actionController = TwitterActionController()
45 | actionController.addAction(Action(ActionData(title: "Xmartlabs", subtitle: "@xmartlabs", image: UIImage(named: "tw-xmartlabs")!), style: .default, handler: { action in
46 | }))
47 | actionController.addAction(Action(ActionData(title: "Miguel", subtitle: "@remer88", image: UIImage(named: "tw-remer")!), style: .default, handler: { action in
48 | }))
49 | actionController.headerData = "Accounts"
50 | present(actionController, animated: true, completion: nil)
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/Example/UITests/ExampleUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExampleUITests.swift
3 | // ExampleUITests
4 | //
5 | // Created by Martin Barreto on 11/16/15.
6 | // Copyright © 2015 Xmartlabs. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class ExampleUITests: XCTestCase {
12 |
13 | override func setUp() {
14 | super.setUp()
15 |
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 |
18 | // In UI tests it is usually best to stop immediately when a failure occurs.
19 | continueAfterFailure = false
20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
21 | XCUIApplication().launch()
22 |
23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
24 | }
25 |
26 | override func tearDown() {
27 | // Put teardown code here. This method is called after the invocation of each test method in the class.
28 | super.tearDown()
29 | }
30 |
31 | func testExample() {
32 | // Use recording to get started writing UI tests.
33 | // Use XCTAssert and related functions to verify your tests produce the correct results.
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Example/UITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Example/YouTubeExampleViewController.swift:
--------------------------------------------------------------------------------
1 | // YouTubeExampleViewController.swift
2 | // XLActionController ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 | import XLActionController
27 |
28 | class YouTubeExampleViewController: UIViewController {
29 |
30 | override func viewWillAppear(_ animated: Bool) {
31 | super.viewWillAppear(animated)
32 | navigationController?.setNavigationBarHidden(true, animated: animated)
33 | }
34 |
35 | @IBAction func backButtonDidTouch(_ sender: UIButton) {
36 | _ = navigationController?.popViewController(animated: true)
37 | }
38 |
39 | @IBAction func tapGestureDidRecognize(_ sender: UITapGestureRecognizer) {
40 |
41 | let actionController = YoutubeActionController()
42 |
43 | actionController.addAction(Action(ActionData(title: "Add to Watch Later", image: UIImage(named: "yt-add-to-watch-later-icon")!), style: .default, handler: { action in
44 | }))
45 | actionController.addAction(Action(ActionData(title: "Add to Playlist...", image: UIImage(named: "yt-add-to-playlist-icon")!), style: .default, handler: { action in
46 | }))
47 | actionController.addAction(Action(ActionData(title: "Share...", image: UIImage(named: "yt-share-icon")!), style: .default, handler: { action in
48 | }))
49 | actionController.addAction(Action(ActionData(title: "Cancel", image: UIImage(named: "yt-cancel-icon")!), style: .cancel, handler: nil))
50 |
51 | present(actionController, animated: true, completion: nil)
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 XMARTLABS (http://xmartlabs.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 |
--------------------------------------------------------------------------------
/Media/demo_periscope.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Media/demo_periscope.gif
--------------------------------------------------------------------------------
/Media/demo_skype.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Media/demo_skype.gif
--------------------------------------------------------------------------------
/Media/demo_spotify.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Media/demo_spotify.gif
--------------------------------------------------------------------------------
/Media/demo_tweetbot.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Media/demo_tweetbot.gif
--------------------------------------------------------------------------------
/Media/demo_twitter.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Media/demo_twitter.gif
--------------------------------------------------------------------------------
/Media/demo_youtube.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/Media/demo_youtube.gif
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.3
2 |
3 | import PackageDescription
4 |
5 | func getExampleTarget(name: String) -> Target {
6 | return .target(name: "XLActionController_" + name,
7 | dependencies: [Target.Dependency.target(name: "XLActionController")],
8 | path: "Example/CustomActionControllers/\(name)",
9 | sources: ["\(name).swift"],
10 | resources: [Resource.process("\(name)Cell.xib")],
11 | swiftSettings: [SwiftSetting.define("IMPORT_BASE_XLACTIONCONTROLLER")])
12 | }
13 |
14 | let package = Package(
15 | name: "XLActionController",
16 | platforms: [
17 | .iOS(.v9)
18 | ],
19 | products: [
20 | .library(name: "XLActionController", targets: ["XLActionController"]),
21 | .library(name: "XLActionControllerSkype", targets: ["XLActionController_Skype"]),
22 | .library(name: "XLActionControllerPeriscope", targets: ["XLActionController_Periscope"]),
23 | .library(name: "XLActionControllerSpotify", targets: ["XLActionController_Spotify"]),
24 | .library(name: "XLActionControllerTweetbot", targets: ["XLActionController_Tweetbot"]),
25 | .library(name: "XLActionControllerTwitter", targets: ["XLActionController_Twitter"]),
26 | .library(name: "XLActionControllerYoutube", targets: ["XLActionController_Youtube"])
27 | ],
28 | targets: [
29 | .target(name: "XLActionController", path: "Source",
30 | resources: [Resource.process("Resource/ActionCell.xib")]),
31 | getExampleTarget(name: "Periscope"),
32 | getExampleTarget(name: "Skype"),
33 | getExampleTarget(name: "Spotify"),
34 | getExampleTarget(name: "Tweetbot"),
35 | getExampleTarget(name: "Twitter"),
36 | getExampleTarget(name: "Youtube"),
37 | ]
38 | )
39 |
--------------------------------------------------------------------------------
/Resource/ActionCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
38 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/Source/Action.swift:
--------------------------------------------------------------------------------
1 | // Action.swift
2 | // XLActionController ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 |
26 | import Foundation
27 | import UIKit
28 |
29 | public enum ActionStyle {
30 | case `default`
31 | case cancel
32 | case destructive
33 | }
34 |
35 | public struct Action {
36 |
37 | public var enabled: Bool
38 | public var executeImmediatelyOnTouch = false
39 |
40 | public fileprivate(set) var data: T?
41 | public fileprivate(set) var style = ActionStyle.default
42 | public fileprivate(set) var handler: ((Action) -> Void)?
43 |
44 | public init(_ data: T?, style: ActionStyle, executeImmediatelyOnTouch: Bool = false, handler: ((Action) -> Void)?) {
45 | enabled = true
46 | self.executeImmediatelyOnTouch = executeImmediatelyOnTouch
47 | self.data = data
48 | self.style = style
49 | self.handler = handler
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/Source/ActionCell.swift:
--------------------------------------------------------------------------------
1 | // ActionCell.swift
2 | // XLActionController ( https://github.com/xmartlabs/ActionCell )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 |
27 | public protocol SeparatorCellType: NSObjectProtocol {
28 | func showSeparator()
29 | func hideSeparator()
30 | }
31 |
32 | open class ActionCell: UICollectionViewCell, SeparatorCellType {
33 |
34 | @IBOutlet open weak var actionTitleLabel: UILabel?
35 | @IBOutlet open weak var actionImageView: UIImageView?
36 | @IBOutlet open weak var actionDetailLabel: UILabel?
37 | @IBOutlet open weak var separatorView: UIView?
38 |
39 | @IBOutlet open weak var imageViewWidthConstraint: NSLayoutConstraint?
40 |
41 | var imageWidth: CGFloat = 0
42 |
43 | open override func awakeFromNib() {
44 | super.awakeFromNib()
45 |
46 | imageWidth = imageViewWidthConstraint?.constant ?? 0
47 | }
48 |
49 | open func setup(_ title: String?, detail: String?, image: UIImage?) {
50 | actionTitleLabel?.text = title
51 | actionDetailLabel?.text = detail
52 | actionImageView?.image = image
53 |
54 | imageViewWidthConstraint?.constant = image == nil ? 0 : imageWidth
55 |
56 | setNeedsLayout()
57 | }
58 |
59 | open func showSeparator() {
60 | separatorView?.alpha = 1.0
61 | }
62 |
63 | open func hideSeparator() {
64 | separatorView?.alpha = 0.0
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Source/ActionControllerSettings.swift:
--------------------------------------------------------------------------------
1 | // ActionControllerSettings.swiftg
2 | // XLActionController ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 |
27 | public struct ActionControllerSettings {
28 |
29 | /** Struct that contains properties to configure the actions controller's behavior */
30 | public struct Behavior {
31 | /**
32 | * A Boolean value that determines whether the action controller must be dismissed when the user taps the
33 | * background view. Its default value is `true`.
34 | */
35 | public var hideOnTap = true
36 | /**
37 | * A Boolean value that determines whether the action controller must be dismissed when the user scroll down
38 | * the collection view. Its default value is `true`.
39 | *
40 | * @discussion If `scrollEnabled` value is `false`, this property is discarded and the action controller won't
41 | * be dismissed if the user scrolls down the collection view.
42 | */
43 | public var hideOnScrollDown = true
44 | /**
45 | * A Boolean value that determines whether the collectionView's scroll is enabled. Its default value is `false`
46 | */
47 | public var scrollEnabled = false
48 | /**
49 | * A Boolean value that controls whether the collection view scroll bounces past the edge of content and back
50 | * again. Its default value is `false`
51 | */
52 | public var bounces = false
53 | /**
54 | * A Boolean value that determines whether if the collection view layout will use UIDynamics to animate its
55 | * items. Its default value is `false`
56 | */
57 | public var useDynamics = false
58 | /**
59 | * A Boolean value that determines whether the navigation bar will hide when action controller is being
60 | * presented. Its default value is `true`
61 | */
62 | public var hideNavigationBarOnShow = true
63 | }
64 |
65 | /** Struct that contains properties to configure the cancel view */
66 | public struct CancelViewStyle {
67 | /**
68 | * A Boolean value that determines whether cancel view is shown. Its default value is `false`. Its default
69 | * value is `false`.
70 | */
71 | public var showCancel = false
72 | /**
73 | * The cancel view's title. Its default value is "Cancel".
74 | */
75 | public var title: String? = "Cancel"
76 | /**
77 | * The cancel view's title Font.
78 | */
79 | public var titleFont: String = UIFont.systemFont(ofSize: 14).fontName
80 | /**
81 | * The cancel view's title Font Size.
82 | */
83 | public var titleSize: CGFloat = 14.0
84 | /**
85 | * The cancel view's height. Its default value is `60`.
86 | */
87 | public var height = CGFloat(60.0)
88 | /**
89 | * The cancel view's background color. Its default value is `UIColor.blackColor().colorWithAlphaComponent(0.8)`.
90 | */
91 | public var backgroundColor = UIColor.black.withAlphaComponent(0.8)
92 | /**
93 | * The cancel view's title color. Its default value is `UIColor.white`.
94 | */
95 | public var titleColor = UIColor.white
96 | /**
97 | * A Boolean value that determines whether the collection view can be partially covered by the
98 | * cancel view when it is pulled down. Its default value is `false`
99 | */
100 | public var hideCollectionViewBehindCancelView = false
101 | }
102 |
103 | /** Struct that contains properties to configure the collection view's style */
104 | public struct CollectionViewStyle {
105 | /**
106 | * A float that determines the margins between the collection view and the container view's margins.
107 | * Its default value is `0`
108 | */
109 | public var lateralMargin: CGFloat = 0
110 | /**
111 | * A float that determines the cells' height when using UIDynamics to animate items. Its default value is `50`.
112 | */
113 | public var cellHeightWhenDynamicsIsUsed: CGFloat = 50
114 | }
115 |
116 | /** Struct that contains properties to configure the animation when presenting the action controller */
117 | public struct PresentAnimationStyle {
118 | /**
119 | * A float value that is used as damping for the animation block. Its default value is `1.0`.
120 | * @see: animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:
121 | */
122 | public var damping = CGFloat(1.0)
123 | /**
124 | * A float value that is used as delay for the animation block. Its default value is `0.0`.
125 | * @see: animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:
126 | */
127 | public var delay = TimeInterval(0.0)
128 | /**
129 | * A float value that determines the animation duration. Its default value is `0.7`.
130 | * @see: animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:
131 | */
132 | public var duration = TimeInterval(0.7)
133 | /**
134 | * A float value that is used as `springVelocity` for the animation block. Its default value is `0.0`.
135 | * @see: animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:
136 | */
137 | public var springVelocity = CGFloat(0.0)
138 | /**
139 | * A mask of options indicating how you want to perform the animations. Its default value is `UIViewAnimationOptions.CurveEaseOut`.
140 | * @see: animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:
141 | */
142 | public var options = UIView.AnimationOptions.curveEaseOut
143 | }
144 |
145 | /** Struct that contains properties to configure the animation when dismissing the action controller */
146 | public struct DismissAnimationStyle {
147 | /**
148 | * A float value that is used as damping for the animation block. Its default value is `1.0`.
149 | * @see: animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:
150 | */
151 | public var damping = CGFloat(1.0)
152 | /**
153 | * A float value that is used as delay for the animation block. Its default value is `0.0`.
154 | * @see: animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:
155 | */
156 | public var delay = TimeInterval(0.0)
157 | /**
158 | * A float value that determines the animation duration. Its default value is `0.7`.
159 | * @see: animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:
160 | */
161 | public var duration = TimeInterval(0.7)
162 | /**
163 | * A float value that is used as `springVelocity` for the animation block. Its default value is `0.0`.
164 | * @see: animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:
165 | */
166 | public var springVelocity = CGFloat(0.0)
167 | /**
168 | * A mask of options indicating how you want to perform the animations. Its default value is `UIViewAnimationOptions.CurveEaseIn`.
169 | * @see: animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:
170 | */
171 | public var options = UIView.AnimationOptions.curveEaseIn
172 | /**
173 | * A float value that makes the action controller's to be animated until the bottomof the screen plus this value.
174 | */
175 | public var offset = CGFloat(0)
176 | }
177 |
178 | /** Struct that contains all properties related to presentation & dismissal animations */
179 | public struct AnimationStyle {
180 | /**
181 | * A size value that is used to scale the presenting view controller when the action controller is being
182 | * presented. If `nil` is set, then the presenting view controller won't be scaled. Its default value is
183 | * `(0.9, 0.9)`.
184 | */
185 | public var scale: CGSize? = CGSize(width: 0.9, height: 0.9)
186 | /** Stores presentation animation properties */
187 | public var present = PresentAnimationStyle()
188 | /** Stores dismissal animation properties */
189 | public var dismiss = DismissAnimationStyle()
190 | }
191 |
192 | /** Struct that contains properties related to the status bar's appearance */
193 | public struct StatusBarStyle {
194 | /**
195 | * A Boolean value that determines whether the status bar should be visible or hidden when the action controller
196 | * is visible. Its default value is `true`.
197 | */
198 | public var showStatusBar = true
199 | /**
200 | * A value that determines the style of the device’s status bar when the action controller is visible. Its
201 | * default value is `UIStatusBarStyle.LightContent`.
202 | */
203 | public var style = UIStatusBarStyle.lightContent
204 | /**
205 | * A boolean value that determines whether the action controller takes over control of status bar appearance from the presenting
206 | * view controller. Its default value is `true`.
207 | *
208 | * For more information refer to `UIViewController.modalPresentationCapturesStatusBarAppearance`,
209 | * https://developer.apple.com/reference/uikit/uiviewcontroller/1621453-modalpresentationcapturesstatusb
210 | */
211 | public var modalPresentationCapturesStatusBarAppearance = true
212 | }
213 |
214 | /** Stores the behavior's properties values */
215 | public var behavior = Behavior()
216 | /** Stores the cancel view's properties values */
217 | public var cancelView = CancelViewStyle()
218 | /** Stores the collection view's properties values */
219 | public var collectionView = CollectionViewStyle()
220 | /** Stores the animations' properties values */
221 | public var animation = AnimationStyle()
222 | /** Stores the status bar's properties values */
223 | public var statusBar = StatusBarStyle()
224 |
225 | /**
226 | * Create the default settings
227 | * @return The default value for settings
228 | */
229 | public static func defaultSettings() -> ActionControllerSettings {
230 | return ActionControllerSettings()
231 | }
232 | }
233 |
--------------------------------------------------------------------------------
/Source/ActionData.swift:
--------------------------------------------------------------------------------
1 | // ActionData.swift
2 | // ActionData ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import Foundation
26 | import UIKit
27 |
28 | public struct ActionData {
29 |
30 | public fileprivate(set) var title: String?
31 | public fileprivate(set) var subtitle: String?
32 | public fileprivate(set) var image: UIImage?
33 |
34 | public init(title: String) {
35 | self.title = title
36 | }
37 |
38 | public init(title: String, subtitle: String) {
39 | self.init(title: title)
40 | self.subtitle = subtitle
41 | }
42 |
43 | public init(title: String, subtitle: String, image: UIImage) {
44 | self.init(title: title, subtitle: subtitle)
45 | self.image = image
46 | }
47 |
48 | public init(title: String, image: UIImage) {
49 | self.init(title: title)
50 | self.image = image
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Source/DynamicCollectionViewFlowLayout.swift:
--------------------------------------------------------------------------------
1 | // DynamicCollectionViewFlowLayout.swiftg
2 | // DynamicCollectionViewFlowLayout ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( whttp://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | import UIKit
26 |
27 | open class DynamicCollectionViewFlowLayout: UICollectionViewFlowLayout {
28 |
29 |
30 | // MARK: - Properties definition
31 |
32 | open var dynamicAnimator: UIDynamicAnimator?
33 | open var itemsAligment = UIControl.ContentHorizontalAlignment.center
34 |
35 | open lazy var collisionBehavior: UICollisionBehavior? = {
36 | let collision = UICollisionBehavior(items: [])
37 | return collision
38 | }()
39 |
40 | open lazy var dynamicItemBehavior: UIDynamicItemBehavior? = {
41 | let dynamic = UIDynamicItemBehavior(items: [])
42 | dynamic.allowsRotation = false
43 | return dynamic
44 | }()
45 |
46 | open lazy var gravityBehavior: UIGravityBehavior? = {
47 | let gravity = UIGravityBehavior(items: [])
48 | gravity.gravityDirection = CGVector(dx: 0, dy: -1)
49 | gravity.magnitude = 4.0
50 | return gravity
51 | }()
52 |
53 | open var useDynamicAnimator = false {
54 | didSet(newValue) {
55 | guard useDynamicAnimator != newValue else {
56 | return
57 | }
58 |
59 | if useDynamicAnimator {
60 | dynamicAnimator = UIDynamicAnimator(collectionViewLayout: self)
61 |
62 | dynamicAnimator!.addBehavior(collisionBehavior!)
63 | dynamicAnimator!.addBehavior(dynamicItemBehavior!)
64 | dynamicAnimator!.addBehavior(gravityBehavior!)
65 | }
66 | }
67 | }
68 |
69 | // MARK: - Intialize
70 |
71 | override init() {
72 | super.init()
73 | initialize()
74 | }
75 |
76 | required public init?(coder aDecoder: NSCoder) {
77 | super.init(coder: aDecoder)
78 | initialize()
79 | }
80 |
81 | fileprivate func initialize() {
82 | minimumInteritemSpacing = 0
83 | minimumLineSpacing = 0
84 | }
85 |
86 | // MARK: - UICollectionViewFlowLayout overrides
87 |
88 | override open func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
89 | guard let animator = dynamicAnimator else {
90 | return super.layoutAttributesForElements(in: rect)
91 | }
92 |
93 | let items = animator.items(in: rect) as NSArray
94 | return items.compactMap { $0 as? UICollectionViewLayoutAttributes }
95 | }
96 |
97 | override open func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
98 | let indexPath = indexPath
99 |
100 | guard let animator = dynamicAnimator else {
101 | return super.layoutAttributesForItem(at: indexPath)
102 | }
103 |
104 | return animator.layoutAttributesForCell(at: indexPath) ?? setupAttributesForIndexPath(indexPath)
105 | }
106 |
107 | override open func prepare(forCollectionViewUpdates updateItems: [UICollectionViewUpdateItem]) {
108 | super.prepare(forCollectionViewUpdates: updateItems)
109 |
110 | updateItems.filter { $0.updateAction == .insert && layoutAttributesForItem(at: $0.indexPathAfterUpdate!) == nil } .forEach {
111 | setupAttributesForIndexPath($0.indexPathAfterUpdate)
112 | }
113 | }
114 |
115 | // MARK: - Helpers
116 |
117 | fileprivate func topForItemAt(indexPath: IndexPath) -> CGFloat {
118 | guard let unwrappedCollectionView = collectionView else {
119 | return CGFloat(0.0)
120 | }
121 |
122 | // Top within item's section
123 | var top = CGFloat((indexPath as NSIndexPath).item) * itemSize.height
124 |
125 | if (indexPath as NSIndexPath).section > 0 {
126 | let lastItemOfPrevSection = unwrappedCollectionView.numberOfItems(inSection: (indexPath as NSIndexPath).section - 1)
127 | // Add previous sections height recursively. We have to add the sectionInsets and the last section's item height
128 | let inset = (unwrappedCollectionView.delegate as? UICollectionViewDelegateFlowLayout)?.collectionView?(unwrappedCollectionView, layout: self, insetForSectionAt: (indexPath as NSIndexPath).section) ?? sectionInset
129 | top += topForItemAt(indexPath: IndexPath(item: lastItemOfPrevSection - 1, section: (indexPath as NSIndexPath).section - 1)) + inset.bottom + inset.top + itemSize.height
130 | }
131 |
132 | return top
133 | }
134 |
135 | private func isRTL(for view: UIView) -> Bool {
136 | return UIView.userInterfaceLayoutDirection(for: view.semanticContentAttribute) == .rightToLeft
137 | }
138 |
139 | @discardableResult
140 | func setupAttributesForIndexPath(_ indexPath: IndexPath?) -> UICollectionViewLayoutAttributes? {
141 | guard let indexPath = indexPath, let animator = dynamicAnimator, let collectionView = collectionView else {
142 | return nil
143 | }
144 |
145 | let delegate: UICollectionViewDelegateFlowLayout = collectionView.delegate as! UICollectionViewDelegateFlowLayout
146 |
147 | let collectionItemSize = delegate.collectionView!(collectionView, layout: self, sizeForItemAt: indexPath)
148 |
149 | // UIDynamic animator will animate this item from initialFrame to finalFrame.
150 |
151 | // Items will be animated from far bottom to its final position in the collection view layout
152 | let originY = collectionView.frame.size.height - collectionView.contentInset.top
153 | var frame = CGRect(x: 0, y: topForItemAt(indexPath: indexPath), width: collectionItemSize.width, height: collectionItemSize.height)
154 | var initialFrame = CGRect(x: 0, y: originY + frame.origin.y, width: collectionItemSize.width, height: collectionItemSize.height)
155 |
156 | // Calculate x position depending on alignment value
157 |
158 | let collectionViewContentWidth = collectionView.bounds.size.width - collectionView.contentInset.left - collectionView.contentInset.right
159 | let rightMargin = (collectionViewContentWidth - frame.size.width)
160 | let leftMargin = CGFloat(0.0)
161 |
162 | var translationX: CGFloat
163 | switch itemsAligment {
164 | case .center:
165 | translationX = (collectionViewContentWidth - frame.size.width) * 0.5
166 | case .fill, .left:
167 | translationX = leftMargin
168 | case .right:
169 | translationX = rightMargin
170 | case .leading:
171 | translationX = isRTL(for: collectionView) ? rightMargin : leftMargin
172 | case .trailing:
173 | translationX = isRTL(for: collectionView) ? leftMargin : rightMargin
174 | @unknown default:
175 | translationX = isRTL(for: collectionView) ? rightMargin : leftMargin
176 | }
177 |
178 | frame.origin.x = translationX
179 | initialFrame.origin.x = translationX
180 |
181 | let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
182 | attributes.frame = initialFrame
183 |
184 | let attachmentBehavior: UIAttachmentBehavior
185 |
186 | let collisionBehavior = UICollisionBehavior(items: [attributes])
187 |
188 | let itemBehavior = UIDynamicItemBehavior(items: [attributes])
189 | itemBehavior.allowsRotation = false
190 |
191 | if (indexPath as NSIndexPath).item == 0 {
192 | let mass = CGFloat(collectionView.numberOfItems(inSection: (indexPath as NSIndexPath).section))
193 |
194 | itemBehavior.elasticity = (0.70 / mass)
195 |
196 | var topMargin = CGFloat(1.5)
197 | if (indexPath as NSIndexPath).section > 0 {
198 | topMargin -= sectionInset.top + sectionInset.bottom
199 | }
200 | let fromPoint = CGPoint(x: frame.minX, y: frame.minY + topMargin)
201 | let toPoint = CGPoint(x: frame.maxX, y: fromPoint.y)
202 | collisionBehavior.addBoundary(withIdentifier: "top" as NSCopying, from: fromPoint, to: toPoint)
203 |
204 | attachmentBehavior = UIAttachmentBehavior(item: attributes, attachedToAnchor:CGPoint(x: frame.midX, y: frame.midY))
205 | attachmentBehavior.length = 1
206 | attachmentBehavior.damping = 0.30 * sqrt(mass)
207 | attachmentBehavior.frequency = 5.0
208 |
209 | } else {
210 | itemBehavior.elasticity = 0.0
211 |
212 | let fromPoint = CGPoint(x: frame.minX, y: frame.minY)
213 | let toPoint = CGPoint(x: frame.maxX, y: fromPoint.y)
214 | collisionBehavior.addBoundary(withIdentifier: "top" as NSCopying, from: fromPoint, to: toPoint)
215 |
216 | let prevPath = IndexPath(item: (indexPath as NSIndexPath).item - 1, section: (indexPath as NSIndexPath).section)
217 | let prevItemAttributes = layoutAttributesForItem(at: prevPath)!
218 | attachmentBehavior = UIAttachmentBehavior(item: attributes, attachedTo: prevItemAttributes)
219 | attachmentBehavior.length = itemSize.height
220 | attachmentBehavior.damping = 0.0
221 | attachmentBehavior.frequency = 0.0
222 | }
223 |
224 | animator.addBehavior(attachmentBehavior)
225 | animator.addBehavior(collisionBehavior)
226 | animator.addBehavior(itemBehavior)
227 |
228 | return attributes
229 | }
230 |
231 | open override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
232 | guard let animator = dynamicAnimator else {
233 | return super.shouldInvalidateLayout(forBoundsChange: newBounds)
234 | }
235 |
236 | guard let unwrappedCollectionView = collectionView else {
237 | return super.shouldInvalidateLayout(forBoundsChange: newBounds)
238 | }
239 |
240 | animator.behaviors
241 | .filter { $0 is UIAttachmentBehavior || $0 is UICollisionBehavior || $0 is UIDynamicItemBehavior}
242 | .forEach { animator.removeBehavior($0) }
243 |
244 | for section in 0..
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 | $(MARKETING_VERSION)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Source/XLActionController.h:
--------------------------------------------------------------------------------
1 | // XLActionController.swiftg
2 | // XLActionController ( https://github.com/xmartlabs/XLActionController )
3 | //
4 | // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
5 | //
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | #import
26 |
27 | //! Project version number for XLActionController.
28 | FOUNDATION_EXPORT double XLActionControllerVersionNumber;
29 |
30 | //! Project version string for XLActionController.
31 | FOUNDATION_EXPORT const unsigned char XLActionControllerVersionString[];
32 |
33 | // In this header, you should import all the public headers of your framework using statements like #import
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Tests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Tests/XLActionControllerTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // XLActionControllerTests.swift
3 | // XLActionControllerTests
4 | //
5 | // Created by Martin Barreto on 11/16/15.
6 | // Copyright © 2015 Xmartlabs. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import XLActionController
11 |
12 | class XLActionControllerTests: 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 |
--------------------------------------------------------------------------------
/XLActionController.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmartlabs/XLActionController/c688f2606665cd1aa14a297ae3353f20b3a8ef86/XLActionController.png
--------------------------------------------------------------------------------
/XLActionController.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 | spec.name = 'XLActionController'
3 | spec.version = '5.1.0'
4 | spec.license = 'MIT'
5 | spec.summary = 'Fully customizable and extensible action sheet controller written in Swift'
6 | spec.homepage = 'https://github.com/xmartlabs/XLActionController'
7 | spec.social_media_url = 'https://twitter.com/xmartlabs'
8 | spec.authors = { 'Miguel Revetria' => 'miguel@xmartlabs.com', 'Martin Barreto' => 'martin@xmartlabs.com' }
9 | spec.source = { :git => 'https://github.com/xmartlabs/XLActionController.git', :tag => spec.version }
10 | spec.ios.deployment_target = '9.3'
11 | spec.ios.frameworks = 'UIKit', 'Foundation', 'CoreGraphics'
12 | spec.requires_arc = true
13 | spec.swift_version = '5.0'
14 |
15 | # Core subspec
16 | spec.subspec 'Core' do |core|
17 | core.source_files = ['Source/*.swift', 'Source/*.xib']
18 | core.resources = 'Resource/*.xib'
19 | end
20 |
21 | # One subspec for each example provided by the library
22 | subspecs = [
23 | 'Periscope',
24 | 'Skype',
25 | 'Spotify',
26 | 'Tweetbot',
27 | 'Twitter',
28 | 'Youtube'
29 | ]
30 |
31 | subspecs.each do |name|
32 | spec.subspec name do |subspec|
33 | subspec.dependency 'XLActionController/Core'
34 | subspec.source_files = ["Example/CustomActionControllers/#{name}/#{name}.swift", "Example/CustomActionControllers/#{name}/#{name}*.xib"]
35 | end
36 | end
37 |
38 | # By default install just the Core subspec code
39 | spec.default_subspec = 'Core'
40 | end
41 |
--------------------------------------------------------------------------------
/XLActionController.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 28473B871C109E4900A8105F /* XLActionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28473B851C109E3F00A8105F /* XLActionControllerTests.swift */; };
11 | 28B3B8411BFA668F007337A2 /* ActionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B3B8361BFA668F007337A2 /* ActionCell.swift */; };
12 | 28B3B8421BFA668F007337A2 /* ActionCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28B3B8371BFA668F007337A2 /* ActionCell.xib */; };
13 | 28B3B8431BFA668F007337A2 /* ActionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B3B8381BFA668F007337A2 /* ActionController.swift */; };
14 | 28B3B8441BFA668F007337A2 /* ActionControllerSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B3B8391BFA668F007337A2 /* ActionControllerSettings.swift */; };
15 | 28B3B8451BFA668F007337A2 /* DynamicCollectionViewFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B3B83A1BFA668F007337A2 /* DynamicCollectionViewFlowLayout.swift */; };
16 | 28B3B8471BFA668F007337A2 /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B3B83C1BFA668F007337A2 /* Action.swift */; };
17 | 28B3B84C1BFA6E39007337A2 /* XLActionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 28B3B84B1BFA6E39007337A2 /* XLActionController.h */; settings = {ATTRIBUTES = (Public, ); }; };
18 | 28E191721BFA618F00066B1C /* XLActionController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28E191671BFA618E00066B1C /* XLActionController.framework */; };
19 | C74DEDA425D2C060009A9DFA /* ActionData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C74DEDA225D2C060009A9DFA /* ActionData.swift */; };
20 | /* End PBXBuildFile section */
21 |
22 | /* Begin PBXContainerItemProxy section */
23 | 28E191731BFA618F00066B1C /* PBXContainerItemProxy */ = {
24 | isa = PBXContainerItemProxy;
25 | containerPortal = 28E1915E1BFA618E00066B1C /* Project object */;
26 | proxyType = 1;
27 | remoteGlobalIDString = 28E191661BFA618E00066B1C;
28 | remoteInfo = XLActionController;
29 | };
30 | /* End PBXContainerItemProxy section */
31 |
32 | /* Begin PBXFileReference section */
33 | 28473B851C109E3F00A8105F /* XLActionControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = XLActionControllerTests.swift; path = Tests/XLActionControllerTests.swift; sourceTree = SOURCE_ROOT; };
34 | 28B3B8361BFA668F007337A2 /* ActionCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ActionCell.swift; path = Source/ActionCell.swift; sourceTree = SOURCE_ROOT; };
35 | 28B3B8371BFA668F007337A2 /* ActionCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ActionCell.xib; sourceTree = ""; };
36 | 28B3B8381BFA668F007337A2 /* ActionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ActionController.swift; path = Source/ActionController.swift; sourceTree = SOURCE_ROOT; };
37 | 28B3B8391BFA668F007337A2 /* ActionControllerSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ActionControllerSettings.swift; path = Source/ActionControllerSettings.swift; sourceTree = SOURCE_ROOT; };
38 | 28B3B83A1BFA668F007337A2 /* DynamicCollectionViewFlowLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DynamicCollectionViewFlowLayout.swift; path = Source/DynamicCollectionViewFlowLayout.swift; sourceTree = SOURCE_ROOT; };
39 | 28B3B83C1BFA668F007337A2 /* Action.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Action.swift; path = Source/Action.swift; sourceTree = SOURCE_ROOT; };
40 | 28B3B84B1BFA6E39007337A2 /* XLActionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XLActionController.h; path = Source/XLActionController.h; sourceTree = SOURCE_ROOT; };
41 | 28E191671BFA618E00066B1C /* XLActionController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = XLActionController.framework; sourceTree = BUILT_PRODUCTS_DIR; };
42 | 28E1916C1BFA618F00066B1C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
43 | 28E191711BFA618F00066B1C /* XLActionControllerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XLActionControllerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
44 | 28E191781BFA618F00066B1C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
45 | C74DED9925D2B82A009A9DFA /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; };
46 | C74DEDA225D2C060009A9DFA /* ActionData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionData.swift; sourceTree = ""; };
47 | /* End PBXFileReference section */
48 |
49 | /* Begin PBXFrameworksBuildPhase section */
50 | 28E191631BFA618E00066B1C /* Frameworks */ = {
51 | isa = PBXFrameworksBuildPhase;
52 | buildActionMask = 2147483647;
53 | files = (
54 | );
55 | runOnlyForDeploymentPostprocessing = 0;
56 | };
57 | 28E1916E1BFA618F00066B1C /* Frameworks */ = {
58 | isa = PBXFrameworksBuildPhase;
59 | buildActionMask = 2147483647;
60 | files = (
61 | 28E191721BFA618F00066B1C /* XLActionController.framework in Frameworks */,
62 | );
63 | runOnlyForDeploymentPostprocessing = 0;
64 | };
65 | /* End PBXFrameworksBuildPhase section */
66 |
67 | /* Begin PBXGroup section */
68 | 28E1915D1BFA618E00066B1C = {
69 | isa = PBXGroup;
70 | children = (
71 | EA2CFE281FBD2FBB00CAE00E /* Resource */,
72 | 28E191691BFA618E00066B1C /* Source */,
73 | 28E191751BFA618F00066B1C /* Tests */,
74 | C74DEDDE25D319F7009A9DFA /* Package */,
75 | 28E191681BFA618E00066B1C /* Products */,
76 | );
77 | sourceTree = "";
78 | };
79 | 28E191681BFA618E00066B1C /* Products */ = {
80 | isa = PBXGroup;
81 | children = (
82 | 28E191671BFA618E00066B1C /* XLActionController.framework */,
83 | 28E191711BFA618F00066B1C /* XLActionControllerTests.xctest */,
84 | );
85 | name = Products;
86 | sourceTree = "";
87 | };
88 | 28E191691BFA618E00066B1C /* Source */ = {
89 | isa = PBXGroup;
90 | children = (
91 | C74DEDA225D2C060009A9DFA /* ActionData.swift */,
92 | 28B3B84B1BFA6E39007337A2 /* XLActionController.h */,
93 | 28B3B8361BFA668F007337A2 /* ActionCell.swift */,
94 | 28B3B8381BFA668F007337A2 /* ActionController.swift */,
95 | 28B3B8391BFA668F007337A2 /* ActionControllerSettings.swift */,
96 | 28B3B83A1BFA668F007337A2 /* DynamicCollectionViewFlowLayout.swift */,
97 | 28B3B83C1BFA668F007337A2 /* Action.swift */,
98 | 28E1916C1BFA618F00066B1C /* Info.plist */,
99 | );
100 | path = Source;
101 | sourceTree = "";
102 | };
103 | 28E191751BFA618F00066B1C /* Tests */ = {
104 | isa = PBXGroup;
105 | children = (
106 | 28473B851C109E3F00A8105F /* XLActionControllerTests.swift */,
107 | 28E191781BFA618F00066B1C /* Info.plist */,
108 | );
109 | path = Tests;
110 | sourceTree = "";
111 | };
112 | C74DEDDE25D319F7009A9DFA /* Package */ = {
113 | isa = PBXGroup;
114 | children = (
115 | C74DED9925D2B82A009A9DFA /* Package.swift */,
116 | );
117 | name = Package;
118 | sourceTree = "";
119 | };
120 | EA2CFE281FBD2FBB00CAE00E /* Resource */ = {
121 | isa = PBXGroup;
122 | children = (
123 | 28B3B8371BFA668F007337A2 /* ActionCell.xib */,
124 | );
125 | path = Resource;
126 | sourceTree = "";
127 | };
128 | /* End PBXGroup section */
129 |
130 | /* Begin PBXHeadersBuildPhase section */
131 | 28E191641BFA618E00066B1C /* Headers */ = {
132 | isa = PBXHeadersBuildPhase;
133 | buildActionMask = 2147483647;
134 | files = (
135 | 28B3B84C1BFA6E39007337A2 /* XLActionController.h in Headers */,
136 | );
137 | runOnlyForDeploymentPostprocessing = 0;
138 | };
139 | /* End PBXHeadersBuildPhase section */
140 |
141 | /* Begin PBXNativeTarget section */
142 | 28E191661BFA618E00066B1C /* XLActionController */ = {
143 | isa = PBXNativeTarget;
144 | buildConfigurationList = 28E1917B1BFA618F00066B1C /* Build configuration list for PBXNativeTarget "XLActionController" */;
145 | buildPhases = (
146 | 28E191621BFA618E00066B1C /* Sources */,
147 | 28E191631BFA618E00066B1C /* Frameworks */,
148 | 28E191641BFA618E00066B1C /* Headers */,
149 | 28E191651BFA618E00066B1C /* Resources */,
150 | );
151 | buildRules = (
152 | );
153 | dependencies = (
154 | );
155 | name = XLActionController;
156 | productName = XLActionController;
157 | productReference = 28E191671BFA618E00066B1C /* XLActionController.framework */;
158 | productType = "com.apple.product-type.framework";
159 | };
160 | 28E191701BFA618F00066B1C /* XLActionControllerTests */ = {
161 | isa = PBXNativeTarget;
162 | buildConfigurationList = 28E1917E1BFA618F00066B1C /* Build configuration list for PBXNativeTarget "XLActionControllerTests" */;
163 | buildPhases = (
164 | 28E1916D1BFA618F00066B1C /* Sources */,
165 | 28E1916E1BFA618F00066B1C /* Frameworks */,
166 | 28E1916F1BFA618F00066B1C /* Resources */,
167 | );
168 | buildRules = (
169 | );
170 | dependencies = (
171 | 28E191741BFA618F00066B1C /* PBXTargetDependency */,
172 | );
173 | name = XLActionControllerTests;
174 | productName = XLActionControllerTests;
175 | productReference = 28E191711BFA618F00066B1C /* XLActionControllerTests.xctest */;
176 | productType = "com.apple.product-type.bundle.unit-test";
177 | };
178 | /* End PBXNativeTarget section */
179 |
180 | /* Begin PBXProject section */
181 | 28E1915E1BFA618E00066B1C /* Project object */ = {
182 | isa = PBXProject;
183 | attributes = {
184 | LastSwiftUpdateCheck = 0710;
185 | LastUpgradeCheck = 1020;
186 | ORGANIZATIONNAME = Xmartlabs;
187 | TargetAttributes = {
188 | 28E191661BFA618E00066B1C = {
189 | CreatedOnToolsVersion = 7.1;
190 | LastSwiftMigration = 1020;
191 | };
192 | 28E191701BFA618F00066B1C = {
193 | CreatedOnToolsVersion = 7.1;
194 | LastSwiftMigration = 1020;
195 | };
196 | };
197 | };
198 | buildConfigurationList = 28E191611BFA618E00066B1C /* Build configuration list for PBXProject "XLActionController" */;
199 | compatibilityVersion = "Xcode 3.2";
200 | developmentRegion = en;
201 | hasScannedForEncodings = 0;
202 | knownRegions = (
203 | en,
204 | Base,
205 | );
206 | mainGroup = 28E1915D1BFA618E00066B1C;
207 | productRefGroup = 28E191681BFA618E00066B1C /* Products */;
208 | projectDirPath = "";
209 | projectRoot = "";
210 | targets = (
211 | 28E191661BFA618E00066B1C /* XLActionController */,
212 | 28E191701BFA618F00066B1C /* XLActionControllerTests */,
213 | );
214 | };
215 | /* End PBXProject section */
216 |
217 | /* Begin PBXResourcesBuildPhase section */
218 | 28E191651BFA618E00066B1C /* Resources */ = {
219 | isa = PBXResourcesBuildPhase;
220 | buildActionMask = 2147483647;
221 | files = (
222 | 28B3B8421BFA668F007337A2 /* ActionCell.xib in Resources */,
223 | );
224 | runOnlyForDeploymentPostprocessing = 0;
225 | };
226 | 28E1916F1BFA618F00066B1C /* Resources */ = {
227 | isa = PBXResourcesBuildPhase;
228 | buildActionMask = 2147483647;
229 | files = (
230 | );
231 | runOnlyForDeploymentPostprocessing = 0;
232 | };
233 | /* End PBXResourcesBuildPhase section */
234 |
235 | /* Begin PBXSourcesBuildPhase section */
236 | 28E191621BFA618E00066B1C /* Sources */ = {
237 | isa = PBXSourcesBuildPhase;
238 | buildActionMask = 2147483647;
239 | files = (
240 | 28B3B8471BFA668F007337A2 /* Action.swift in Sources */,
241 | 28B3B8451BFA668F007337A2 /* DynamicCollectionViewFlowLayout.swift in Sources */,
242 | 28B3B8411BFA668F007337A2 /* ActionCell.swift in Sources */,
243 | C74DEDA425D2C060009A9DFA /* ActionData.swift in Sources */,
244 | 28B3B8441BFA668F007337A2 /* ActionControllerSettings.swift in Sources */,
245 | 28B3B8431BFA668F007337A2 /* ActionController.swift in Sources */,
246 | );
247 | runOnlyForDeploymentPostprocessing = 0;
248 | };
249 | 28E1916D1BFA618F00066B1C /* Sources */ = {
250 | isa = PBXSourcesBuildPhase;
251 | buildActionMask = 2147483647;
252 | files = (
253 | 28473B871C109E4900A8105F /* XLActionControllerTests.swift in Sources */,
254 | );
255 | runOnlyForDeploymentPostprocessing = 0;
256 | };
257 | /* End PBXSourcesBuildPhase section */
258 |
259 | /* Begin PBXTargetDependency section */
260 | 28E191741BFA618F00066B1C /* PBXTargetDependency */ = {
261 | isa = PBXTargetDependency;
262 | target = 28E191661BFA618E00066B1C /* XLActionController */;
263 | targetProxy = 28E191731BFA618F00066B1C /* PBXContainerItemProxy */;
264 | };
265 | /* End PBXTargetDependency section */
266 |
267 | /* Begin XCBuildConfiguration section */
268 | 28E191791BFA618F00066B1C /* Debug */ = {
269 | isa = XCBuildConfiguration;
270 | buildSettings = {
271 | ALWAYS_SEARCH_USER_PATHS = NO;
272 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
273 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
274 | CLANG_CXX_LIBRARY = "libc++";
275 | CLANG_ENABLE_MODULES = YES;
276 | CLANG_ENABLE_OBJC_ARC = YES;
277 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
278 | CLANG_WARN_BOOL_CONVERSION = YES;
279 | CLANG_WARN_COMMA = YES;
280 | CLANG_WARN_CONSTANT_CONVERSION = YES;
281 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
282 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
283 | CLANG_WARN_EMPTY_BODY = YES;
284 | CLANG_WARN_ENUM_CONVERSION = YES;
285 | CLANG_WARN_INFINITE_RECURSION = YES;
286 | CLANG_WARN_INT_CONVERSION = YES;
287 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
288 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
289 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
290 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
291 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
292 | CLANG_WARN_STRICT_PROTOTYPES = YES;
293 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
294 | CLANG_WARN_UNREACHABLE_CODE = YES;
295 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
296 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
297 | COPY_PHASE_STRIP = NO;
298 | CURRENT_PROJECT_VERSION = 1;
299 | DEBUG_INFORMATION_FORMAT = dwarf;
300 | ENABLE_STRICT_OBJC_MSGSEND = YES;
301 | ENABLE_TESTABILITY = YES;
302 | GCC_C_LANGUAGE_STANDARD = gnu99;
303 | GCC_DYNAMIC_NO_PIC = NO;
304 | GCC_NO_COMMON_BLOCKS = YES;
305 | GCC_OPTIMIZATION_LEVEL = 0;
306 | GCC_PREPROCESSOR_DEFINITIONS = (
307 | "DEBUG=1",
308 | "$(inherited)",
309 | );
310 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
311 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
312 | GCC_WARN_UNDECLARED_SELECTOR = YES;
313 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
314 | GCC_WARN_UNUSED_FUNCTION = YES;
315 | GCC_WARN_UNUSED_VARIABLE = YES;
316 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
317 | MTL_ENABLE_DEBUG_INFO = YES;
318 | ONLY_ACTIVE_ARCH = YES;
319 | SDKROOT = iphoneos;
320 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
321 | SWIFT_VERSION = 4.0;
322 | TARGETED_DEVICE_FAMILY = "1,2";
323 | VERSIONING_SYSTEM = "apple-generic";
324 | VERSION_INFO_PREFIX = "";
325 | };
326 | name = Debug;
327 | };
328 | 28E1917A1BFA618F00066B1C /* Release */ = {
329 | isa = XCBuildConfiguration;
330 | buildSettings = {
331 | ALWAYS_SEARCH_USER_PATHS = NO;
332 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
333 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
334 | CLANG_CXX_LIBRARY = "libc++";
335 | CLANG_ENABLE_MODULES = YES;
336 | CLANG_ENABLE_OBJC_ARC = YES;
337 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
338 | CLANG_WARN_BOOL_CONVERSION = YES;
339 | CLANG_WARN_COMMA = YES;
340 | CLANG_WARN_CONSTANT_CONVERSION = YES;
341 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
342 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
343 | CLANG_WARN_EMPTY_BODY = YES;
344 | CLANG_WARN_ENUM_CONVERSION = YES;
345 | CLANG_WARN_INFINITE_RECURSION = YES;
346 | CLANG_WARN_INT_CONVERSION = YES;
347 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
348 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
349 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
350 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
351 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
352 | CLANG_WARN_STRICT_PROTOTYPES = YES;
353 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
354 | CLANG_WARN_UNREACHABLE_CODE = YES;
355 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
356 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
357 | COPY_PHASE_STRIP = NO;
358 | CURRENT_PROJECT_VERSION = 1;
359 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
360 | ENABLE_NS_ASSERTIONS = NO;
361 | ENABLE_STRICT_OBJC_MSGSEND = YES;
362 | GCC_C_LANGUAGE_STANDARD = gnu99;
363 | GCC_NO_COMMON_BLOCKS = YES;
364 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
365 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
366 | GCC_WARN_UNDECLARED_SELECTOR = YES;
367 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
368 | GCC_WARN_UNUSED_FUNCTION = YES;
369 | GCC_WARN_UNUSED_VARIABLE = YES;
370 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
371 | MTL_ENABLE_DEBUG_INFO = NO;
372 | SDKROOT = iphoneos;
373 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
374 | SWIFT_VERSION = 4.0;
375 | TARGETED_DEVICE_FAMILY = "1,2";
376 | VALIDATE_PRODUCT = YES;
377 | VERSIONING_SYSTEM = "apple-generic";
378 | VERSION_INFO_PREFIX = "";
379 | };
380 | name = Release;
381 | };
382 | 28E1917C1BFA618F00066B1C /* Debug */ = {
383 | isa = XCBuildConfiguration;
384 | buildSettings = {
385 | CLANG_ENABLE_MODULES = YES;
386 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
387 | DEFINES_MODULE = YES;
388 | DEVELOPMENT_TEAM = "";
389 | DYLIB_COMPATIBILITY_VERSION = 1;
390 | DYLIB_CURRENT_VERSION = 1;
391 | DYLIB_INSTALL_NAME_BASE = "@rpath";
392 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist";
393 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
394 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
395 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
396 | MARKETING_VERSION = 5.1.0;
397 | PRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.XLActionController;
398 | PRODUCT_NAME = "$(TARGET_NAME)";
399 | SKIP_INSTALL = YES;
400 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
401 | SWIFT_VERSION = 5.0;
402 | };
403 | name = Debug;
404 | };
405 | 28E1917D1BFA618F00066B1C /* Release */ = {
406 | isa = XCBuildConfiguration;
407 | buildSettings = {
408 | CLANG_ENABLE_MODULES = YES;
409 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
410 | DEFINES_MODULE = YES;
411 | DEVELOPMENT_TEAM = "";
412 | DYLIB_COMPATIBILITY_VERSION = 1;
413 | DYLIB_CURRENT_VERSION = 1;
414 | DYLIB_INSTALL_NAME_BASE = "@rpath";
415 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist";
416 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
417 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
418 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
419 | MARKETING_VERSION = 5.1.0;
420 | PRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.XLActionController;
421 | PRODUCT_NAME = "$(TARGET_NAME)";
422 | SKIP_INSTALL = YES;
423 | SWIFT_VERSION = 5.0;
424 | };
425 | name = Release;
426 | };
427 | 28E1917F1BFA618F00066B1C /* Debug */ = {
428 | isa = XCBuildConfiguration;
429 | buildSettings = {
430 | DEVELOPMENT_TEAM = "";
431 | INFOPLIST_FILE = Tests/Info.plist;
432 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
433 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
434 | PRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.XLActionControllerTests;
435 | PRODUCT_NAME = "$(TARGET_NAME)";
436 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
437 | SWIFT_VERSION = 5.0;
438 | };
439 | name = Debug;
440 | };
441 | 28E191801BFA618F00066B1C /* Release */ = {
442 | isa = XCBuildConfiguration;
443 | buildSettings = {
444 | DEVELOPMENT_TEAM = "";
445 | INFOPLIST_FILE = Tests/Info.plist;
446 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
447 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
448 | PRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.XLActionControllerTests;
449 | PRODUCT_NAME = "$(TARGET_NAME)";
450 | SWIFT_VERSION = 5.0;
451 | };
452 | name = Release;
453 | };
454 | /* End XCBuildConfiguration section */
455 |
456 | /* Begin XCConfigurationList section */
457 | 28E191611BFA618E00066B1C /* Build configuration list for PBXProject "XLActionController" */ = {
458 | isa = XCConfigurationList;
459 | buildConfigurations = (
460 | 28E191791BFA618F00066B1C /* Debug */,
461 | 28E1917A1BFA618F00066B1C /* Release */,
462 | );
463 | defaultConfigurationIsVisible = 0;
464 | defaultConfigurationName = Release;
465 | };
466 | 28E1917B1BFA618F00066B1C /* Build configuration list for PBXNativeTarget "XLActionController" */ = {
467 | isa = XCConfigurationList;
468 | buildConfigurations = (
469 | 28E1917C1BFA618F00066B1C /* Debug */,
470 | 28E1917D1BFA618F00066B1C /* Release */,
471 | );
472 | defaultConfigurationIsVisible = 0;
473 | defaultConfigurationName = Release;
474 | };
475 | 28E1917E1BFA618F00066B1C /* Build configuration list for PBXNativeTarget "XLActionControllerTests" */ = {
476 | isa = XCConfigurationList;
477 | buildConfigurations = (
478 | 28E1917F1BFA618F00066B1C /* Debug */,
479 | 28E191801BFA618F00066B1C /* Release */,
480 | );
481 | defaultConfigurationIsVisible = 0;
482 | defaultConfigurationName = Release;
483 | };
484 | /* End XCConfigurationList section */
485 | };
486 | rootObject = 28E1915E1BFA618E00066B1C /* Project object */;
487 | }
488 |
--------------------------------------------------------------------------------
/XLActionController.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/XLActionController.xcodeproj/xcshareddata/xcschemes/XLActionController.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
65 |
71 |
72 |
73 |
74 |
75 |
76 |
82 |
83 |
89 |
90 |
91 |
92 |
94 |
95 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/XLActionController.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/XLActionController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------