Fully customizable and extensible action sheet controller written in Swift

Overview

XLActionController

Build status Platform iOS Swift 5 compatible Carthage compatible CocoaPods compatible License: MIT

By XMARTLABS.

XLActionController is an extensible library to quickly create any custom action sheet controller.

Examples

The action sheet controllers shown above were entirely created using XLActionController and are included in the Examples. To run the Example project: clone XLActionController repository, open XLActionController workspace and run the Example project.

The code snippet below shows how to present the Tweetbot action sheet controller:

let actionController = TweetbotActionController()

actionController.addAction(Action("View Details", style: .default, handler: { action in
  // do something useful
}))
actionController.addAction(Action("View Retweets", style: .default, handler: { action in
  // do something useful
}))
actionController.addAction(Action("View in Favstar", style: .default, handler: { action in
  // do something useful
}))
actionController.addAction(Action("Translate", style: .default, executeImmediatelyOnTouch: true, handler: { action in
  // do something useful
}))

actionController.addSection(Section())
actionController.addAction(Action("Cancel", style: .cancel, handler:nil))

present(actionController, animated: true, completion: nil)

As you may have noticed, the library usage looks pretty similar to UIAlertController.

Actions' handlers are executed after the alert controller is dismissed from screen. If you want, you can change this passing true to the action's constructor to the argument executeImmediatelyOnTouch.

Behind the scenes XLActionController uses a UICollectionView to display the action sheet.

Usage

First create a custom action sheet view controller by extending from the ActionController generic class. For details on how to create a custom action sheet controller look at the Extensibility section.

For instance, let's suppose we've already created TwitterActionController.

// Instantiate custom action sheet controller
let actionSheet = TwitterActionController()
// set up a header title
actionSheet.headerData = "Accounts"
// Add some actions, note that the first parameter of `Action` initializer is `ActionData`.
actionSheet.addAction(Action(ActionData(title: "Xmartlabs", subtitle: "@xmartlabs", image: UIImage(named: "tw-xmartlabs")!), style: .default, handler: { action in
   // do something useful
}))
actionSheet.addAction(Action(ActionData(title: "Miguel", subtitle: "@remer88", image: UIImage(named: "tw-remer")!), style: .default, handler: { action in
   // do something useful
}))
// present actionSheet like any other view controller
present(actionSheet, animated: true, completion: nil)

As the code above illustrates, there are no relevant differences compared to the UIAlertController API.

The main difference is that XLActionController works with any header data type and not only the standard UIAlertController title and message properties. Similarly XLActionController's Action works with any data Type and not only the title string.

// XLActionController:
xlActionController.headerData = SpotifyHeaderData(title: "The Fast And The Furious Soundtrack Collection", subtitle: "Various Artists", image: UIImage(named: "sp-header-icon")!)

// vs UIAlertController:
uiActionController.title = "The Fast And The Furious Soundtrack Collection" // no way to pass an image
uiActionController.message = "Various Artists"
// XLActionController:
let xlAction = Action(ActionData(title: "Save Full Album", image: UIImage(named: "sp-add-icon")!), style: .default, handler: { action in })
// notice that we are able to pass an image in addition to the title
xlActionController.addAction(xlAction)

// vs UIAlertController:
let uiAction = UIAlertAction(title: "Xmartlabs", style: .default, handler: { action in }))
uiActionController.addAction(uiAction)

This can be accomplished because XLActionController is a generic type.

Another important difference is that XLActionController provides a way to add action sections as illustrated in the code below:

  actionController.addSection(Section())

and also each section has a data property. This property is generic, so that it can hold any type. This data will be used to create this section's header view.

let section = actionController.addSection(Section())
section.data = "String" // assuming section data Type is String

Each section contains a set of actions. We typically use sections to show a header view above a set of actions.

Extensibility

ActionController uses a UICollectionView to show actions and headers on screen. Actions will be rendered as instances of UICollectionViewCell. You can use your own subclass of UICollectionViewCell by specifying it in the action controller declaration. Additionally, ActionController allows you to specify a global header and a section header. Headers are shown as collection view's supplementary views.

The ActionController class is a generic type that works with any cell, header, section header type and its associated data types.

Create your custom action sheet controller

XLActionController provides extension points to specify a whole new look and feel to our custom sheet controller and to tweak present and dismiss animations. Let's see an example:

// As first step we should extend the ActionController generic type
public class PeriscopeActionController: ActionController<PeriscopeCell, String, PeriscopeHeader, String, UICollectionReusableView, Void> {

    // override init in order to customize behavior and animations
    public override init(nibName nibNameOrNil: String? = nil, bundle nibBundleOrNil: Bundle? = nil) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        // customizing behavior and present/dismiss animations
        settings.behavior.hideOnScrollDown = false
        settings.animation.scale = nil
        settings.animation.present.duration = 0.6
        settings.animation.dismiss.duration = 0.5
        settings.animation.dismiss.options = .curveEaseIn
        settings.animation.dismiss.offset = 30

        // providing a specific collection view cell which will be used to display each action, height parameter expects a block that returns the cell height for a particular action.
        cellSpec = .nibFile(nibName: "PeriscopeCell", bundle: Bundle(for: PeriscopeCell.self), height: { _ in 60})
        // providing a specific view that will render each section header.
        sectionHeaderSpec = .cellClass(height: { _ in 5 })
        // providing a specific view that will render the action sheet header. We calculate its height according the text that should be displayed.
        headerSpec = .cellClass(height: { [weak self] (headerData: String) in
            guard let me = self else { return 0 }
            let label = UILabel(frame: CGRect(x: 0, y: 0, width: me.view.frame.width - 40, height: CGFloat.greatestFiniteMagnitude))
            label.numberOfLines = 0
            label.font = .systemFontOfSize(17.0)
            label.text = headerData
            label.sizeToFit()
            return label.frame.size.height + 20
        })

        // once we specify the views, we have to provide three blocks that will be used to set up these views.
        // block used to setup the header. Header view and the header are passed as block parameters
        onConfigureHeader = { [weak self] header, headerData in
            guard let me = self else { return }
            header.label.frame = CGRect(x: 0, y: 0, width: me.view.frame.size.width - 40, height: CGFloat.greatestFiniteMagnitude)
            header.label.text = headerData
            header.label.sizeToFit()
            header.label.center = CGPoint(x: header.frame.size.width  / 2, y: header.frame.size.height / 2)
        }
        // block used to setup the section header
        onConfigureSectionHeader = { sectionHeader, sectionHeaderData in
            sectionHeader.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
        }
        // block used to setup the collection view cell
        onConfigureCellForAction = { [weak self] cell, action, indexPath in
            cell.setup(action.data, detail: nil, image: nil)
            cell.separatorView?.isHidden = indexPath.item == self!.collectionView.numberOfItems(inSection: indexPath.section) - 1
            cell.alpha = action.enabled ? 1.0 : 0.5
            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)
        }
    }
}

ActionController type declaration:

public class ActionController<ActionViewType: UICollectionViewCell, ActionDataType, HeaderViewType: UICollectionReusableView, HeaderDataType, SectionHeaderViewType: UICollectionReusableView, SectionHeaderDataType>

When extending ActionController we must specify the following view types ActionViewType, HeaderViewType, SectionHeaderViewType. These types are the cell type used to render an action, the view used to render the action sheet header and the view used to render the section header.

Each view type has its associated data: ActionDataType, HeaderDataType, SectionHeaderDataType respectively.

If your custom action sheet doesn't have a header view we can use UICollectionReusableView as HeaderViewType and Void as HeaderDataType. If it doesn't have a section header view you can use UICollectionReusableView as SectionHeaderViewType and Void as SectionHeaderDataType.

The code below shows how we specify these types for the action controllers provided in the example project:

class PeriscopeActionController: ActionController<PeriscopeCell, String, PeriscopeHeader, String, UICollectionReusableView, Void> { ... } // doesn't need to show a section header
class SpotifyActionController: ActionController<SpotifyCell, ActionData, SpotifyHeaderView, SpotifyHeaderData, UICollectionReusableView, Void> { ... } // doesn't need to show a section header
class TwitterActionController: ActionController<TwitterCell, ActionData, TwitterActionControllerHeader, String, UICollectionReusableView, Void> { ... } // doesn't need to show a section header
class YoutubeActionController: ActionController<YoutubeCell, ActionData, UICollectionReusableView, Void, UICollectionReusableView, Void>

Tweaking default style and animation parameters

By following the previous section steps you should already be able to play with your custom action controller. It happens quite often that we need some other customization such as zooming out the presenting view, changing the status bar color or customizing the default present and dismiss animation.

ActionController class defines the settings property of type ActionSheetControllerSettings to tweak all these.

UICollectionView's behavior

// Indicates if the action controller must be dismissed when the user taps the background view. `true` by default.
settings.behavior.hideOnTap: Bool
// Indicates if the action controller must be dismissed when the user scrolls down the collection view. `true` by default.
settings.behavior.hideOnScrollDown: Bool
// Indicates if the collectionView's scroll is enabled. `false` by default.
settings.behavior.scrollEnabled: Bool
// Controls whether the collection view scroll bounces past the edge of content and back again. `false` by default.
settings.behavior.bounces: Bool
// Indicates if the collection view layout will use UIDynamics to animate its items. `false` by default.
settings.behavior.useDynamics: Bool
// Determines whether the navigation bar is hidden when action controller is being presented. `true` by default
settings.hideCollectionViewBehindCancelView: Bool

UICollectionView Style

// Margins between the collection view and the container view's margins. `0` by default
settings.collectionView.lateralMargin: CGFloat
// Cells height when UIDynamics is used to animate items. `50` by default.
settings.collectionView.cellHeightWhenDynamicsIsUsed: CGFloat

Animation settings

Struct that contains all properties related to presentation & dismissal animations

// Used to scale the presenting view controller when the action controller is being presented. If `nil` is set, then the presenting view controller won't be scaled. `(0.9, 0.9)` by default.
settings.animation.scale: CGSize? = CGSize(width: 0.9, height: 0.9)

Present animation settings

// damping value for the animation block. `1.0` by default.
settings.animation.present.damping: CGFloat
// delay for the animation block. `0.0` by default.
settings.animation.present.delay: TimeInterval
// Indicates the animation duration. `0.7` by default.
settings.animation.present.duration: TimeInterval
// Used as `springVelocity` for the animation block. `0.0` by default.
settings.animation.present.springVelocity: CGFloat
// Present animation options. `UIViewAnimationOptions.curveEaseOut` by default.
settings.animation.present.options: UIViewAnimationOptions

Dismiss animation settings

// damping value for the animation block. `1.0` by default.
settings.animation.dismiss.damping: CGFloat
// Used as delay for the animation block. `0.0` by default.
settings.animation.dismiss.delay: TimeInterval
// animation duration. `0.7` by default.
settings.animation.dismiss.duration: TimeInterval
// springVelocity for the animation block. `0.0` by default
settings.animation.dismiss.springVelocity: CGFloat
// dismiss animation options. `UIViewAnimationOptions.curveEaseIn` by default
settings.animation.dismiss.options: UIViewAnimationOptions

StatusBar Style

// Indicates if the status bar should be visible or hidden when the action controller is visible. Its default value is `true`
settings.statusBar.showStatusBar: Bool
// Determines the style of the device’s status bar when the action controller is visible. `UIStatusBarStyle.LightContent` by default.
settings.statusBar.style: UIStatusBarStyle
// Determines whether the action controller takes over control of status bar appearance from the presenting view controller. `true` by default.
settings.statusBar.modalPresentationCapturesStatusBarAppearance: Bool

Cancel view style

Sometimes we need to show a cancel view below the collection view. This is the case of the SpotifyActionController. These properties have nothing to do with the actions added to an action Controller nor with the actions with .Cancel as style value.

 // Indicates if the cancel view is shown. `false` by default.
settings.cancelView.showCancel: Bool
 // Cancel view's title. "Cancel" by default.
settings.cancelView.title: String?
 // Cancel view's height. `60` by default.
settings.cancelView.height: CGFloat
 // Cancel view's background color. `UIColor.black.withAlphaComponent(0.8)` by default.
settings.cancelView.backgroundColor: UIColor
// Indicates if the collection view is partially hidden by the cancelView when it is pulled down.
settings.cancelView.hideCollectionViewBehindCancelView: Bool

Advanced animations

If tweaking previous settings is not enough to make the animations work like you want, XLActionController allows you to change the present/dismiss animation by overriding some functions.

Presentation

open func presentView(_ presentedView: UIView, presentingView: UIView, animationDuration: Double, completion: ((_ completed: Bool) -> Void)?)

The function above is responsible for making the present animation. It encapsulates how the presentation is performed and invokes onWillPresentView, performCustomPresentationAnimation and onDidPresentView to allow you to change a specific point of the animation.

Typically we don't need to override presentView function because overriding either onWillPresentView, performCustomPresentationAnimation or onDidPresentView is enough.

open func onWillPresentView()

onWillPresentView is called before the animation block starts. Any change here won't be animated. It's intended to set the initial animated properties values.

open func performCustomPresentationAnimation(_ presentedView: UIView, presentingView: UIView)

performCustomPresentationAnimation is called from within the main animation block.

open func onDidPresentView()

After the present animation is completed, presentView calls onDidPresentView from within completion callback.

onWillPresentView, performCustomPresentationAnimation, onDidPresentView won't be invoked if you override presentView implementation.

Dismissal

Dismissal animation can be customized in the same way as presentation animation.

open func dismissView(_ presentedView: UIView, presentingView: UIView, animationDuration: Double, completion: ((_ completed: Bool) -> Void)?)

The function above is responsible for making the dismissal animation. It encapsulates how the dismissal animation is performed and invokes onWillDismissView, performCustomDismissingAnimation and onDidDismissView to allow you to change an specific point of the animation.

Typically we don't need to override dismissView method because overriding either onWillDismissView, performCustomDismissingAnimationoronDidDismissView` is enough.

open func onWillDismissView()

Overrides onWillDismissView to perform any set up before the animation begins.

open func performCustomDismissingAnimation(_ presentedView: UIView, presentingView: UIView)

performCustomDismissingAnimation function is invoked from within the main animation block.

open func onDidDismissView()

After the dismissal animation completes, dismissView calls onDidDismissView from within completion callback.

onWillDismissView, performCustomDismissingAnimation, onDidDismissView won't be invoked if you override dismissView implementation.

To show how simple and powerful XLActionController is and give several examples of how to extend ActionController we have mimicked the Skype, Tweetbot, Twitter, Youtube, Periscope and Spotify action controllers.

Requirements

  • iOS 9.3+
  • Xcode 10.2+
  • Swift 5.0+

Getting involved

  • If you want to contribute please feel free to submit pull requests.
  • If you have a feature request please open an issue.
  • If you found a bug or need help please check older issues before submitting an issue.

If you use XLActionController in your app we would love to hear about it! Drop us a line on twitter.

Installation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects.

Specify XLActionController into your project's Podfile:

source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!

target '<Your App Target>' do
  # This will install just the library's core, won't include any examples
  pod 'XLActionController'

  # Uncomment depending on the examples that you want to install
  #pod 'XLActionController/Periscope'
  #pod 'XLActionController/Skype'
  #pod 'XLActionController/Spotify'
  #pod 'XLActionController/Tweetbot'
  #pod 'XLActionController/Twitter'
  #pod 'XLActionController/Youtube'
end

Then run the following command:

$ pod install

Carthage

Carthage is a simple, decentralized dependency manager for Cocoa.

Specify XLActionController into your project's Carthage:

github "xmartlabs/XLActionController" ~> 5.1.0

Manually as Embedded Framework

Clone XLActionController as a git submodule by running the following command from your project root git folder.

$ git submodule add https://github.com/xmartlabs/XLActionController.git

Open XLActionController folder that was created by the previous git submodule command and drag the XLActionController.xcodeproj into the Project Navigator of your application's Xcode project.

Select the XLActionController.xcodeproj in the Project Navigator and verify the deployment target matches with your application deployment target.

Select your project in the Xcode Navigation and then select your application target from the sidebar. Next select the "General" tab and click on the + button under the "Embedded Binaries" section.

Select XLActionController.framework and we are done!

Authors

License

XLActionController is released under MIT license and copyrighted by Xmartlabs SRL.

Issues
  • Update for Xcode 11.0 beta 5

    Update for Xcode 11.0 beta 5

    Hello! 👋 An error appears when building in Xcode 11:

    Command CompileXIB failed with a nonzero exit code
    

    This problem was solved by removing customModuleProvider (i.e. Inherit Module From Target) for cells in xib files. 🤗

    opened by Puasonych 11
  • Example app crashes

    Example app crashes

    Example app crashes in this method in DynamicCollectionViewFlowLayout:

    override open func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { guard let animator = dynamicAnimator else { return super.layoutAttributesForElements(in: rect) }

        return animator.items(in: rect) as? [UICollectionViewLayoutAttributes]
    }
    

    Here's the console log: fatal error: NSArray element failed to match the Swift Array Element type 2017-10-23 16:27:45.074075-0400 Example[18698:29187926] fatal error: NSArray element failed to match the Swift Array Element type (lldb)

    Using XCode 9 with Swift 4. Choose Tweetbot from the tableview sample app options.

    bug 
    opened by shanehartman 7
  • default implementation of insetForSectionAt, UICollectionViewDelegate…

    default implementation of insetForSectionAt, UICollectionViewDelegate…

    …FlowLayout method

    We should be able to define different inset for section in our ActionController subclasses. Actually it's only possible to set a common inset for all section. So I just added a default implementation of the corresponding delegate method in ActionController, then we can override it in our custom subclasses.

    opened by loryhuz 7
  • ActionCell.xib doesn't have an outlet for actionTitleLabelConstraintToContainer or actionTitleLabelConstraintToImageView

    ActionCell.xib doesn't have an outlet for actionTitleLabelConstraintToContainer or actionTitleLabelConstraintToImageView

    XLActionController 3.0.0, XCode 8, iOS9

    *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<XLActionController.ActionCell 0x7ff32660de50> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key actionTitleLabelConstraintToContainer.'

    It appears that actionTitleLabelConstraintToContainer and actionTitleLabelConstraintToImageView don't have outlets in ActionCell.swift.

    bug 
    opened by dmorrow 6
  • Xcode 8 + Swift 3

    Xcode 8 + Swift 3

    opened by mohpor 6
  • Fix error

    Fix error "unexpected duplicate task: CompileXIB " when archiving

    Fix error "unexpected duplicate task: CompileXIB " when archiving with New Build System Xcode 9.

    Solution: Put XIB file into another folder whose name is not "Source" - "Resource" in my PR

    Reference: https://github.com/CocoaPods/CocoaPods/issues/7079

    opened by phucnm 5
  • Xcode 11

    Xcode 11

    I'm using the last release of XLActionController, but compilation is failing due to an issue with the file "ActionCell.xib". In your last commit, you solve this problem (I've copied the file to my project and works fine with it), but I prefer to use the last releases of XLActionController that I can find in CocoaPods without to worry about changes. Could you upload these last changes to a new release? Thank you!!

    opened by Legasquare90 5
  • Added Xcode 8 (Beta 6) support

    Added Xcode 8 (Beta 6) support

    Hi,

    I have added Xcode 8 (Beta 6) support to the library.

    Sincerely, M.

    opened by mohpor 5
  • TweetbotActionController not working with Xcode Version 9.4 (9F1027a)

    TweetbotActionController not working with Xcode Version 9.4 (9F1027a)

    Love the code and have been using it.

    Updated to the latest Xcode just now and since the update, none of my tweetbotActionController items will trigger when called. No action.

    Below is my code to change languages:

     func languageOption() {
            
            let localeEN = Locale(identifier: "en")
            let english = (localeEN as NSLocale).displayName(forKey: NSLocale.Key.identifier, value: "en")
            let localeDE = Locale(identifier: "de")
            let german = (localeDE as NSLocale).displayName(forKey: NSLocale.Key.identifier, value: "de")
            let localeES = Locale(identifier: "es")
            let spanish = (localeES as NSLocale).displayName(forKey: NSLocale.Key.identifier, value: "es")
            let localeFR = Locale(identifier: "fr")
            let french = (localeFR as NSLocale).displayName(forKey: NSLocale.Key.identifier, value: "fr")
            let localeRU = Locale(identifier: "ru")
            let russian = (localeRU as NSLocale).displayName(forKey: NSLocale.Key.identifier, value: "ru")
            let localeCN = Locale(identifier: "zh-Hans")
            let chinese = (localeCN as NSLocale).displayName(forKey: NSLocale.Key.identifier, value: "zh-Hans")
            
            let actionController = TweetbotActionController()
            
            actionController.addAction(Action(english!, style: .default, handler: { action in
                self.englishLanguage ()
            }))
            actionController.addAction(Action(german!, style: .default, handler: { action in
                self.germanLanguage ()
            }))
            actionController.addAction(Action(french!, style: .default, handler: { action in
                self.frenchLanguage ()
            }))
            actionController.addAction(Action(spanish!, style: .default, handler: { action in
                self.spanishLanguage ()
            }))
            actionController.addAction(Action(russian!, style: .default, handler: { action in
                self.russianLanguage ()
            }))
            actionController.addAction(Action(chinese!, style: .default, handler: { action in
                self.chineseLanguage ()
            }))
            actionController.addSection(Section())
            actionController.addAction(Action("Cancel".localized, style: .cancel, handler:nil))
            
            present(actionController, animated: true, completion: {
                self.viewDidLoad()
                self.tableView.reloadData()
            })
            
        }
        
        func englishLanguage (){
            appLanguage = "en"
            userForeignLanguage = false
            NotificationCenter.default.post(name: Notification.Name(rawValue: languageChangedKey), object: self)
            self.viewDidLoad()
            self.tableView.reloadData()
        }
        
        func frenchLanguage () {
            appLanguage = "fr"
            userForeignLanguage = true
            NotificationCenter.default.post(name: Notification.Name(rawValue: languageChangedKey), object: self)
            self.viewDidLoad()
            self.tableView.reloadData()
        }
        
        func germanLanguage () {
            appLanguage = "de"
            userForeignLanguage = true
            NotificationCenter.default.post(name: Notification.Name(rawValue: languageChangedKey), object: self)
            self.viewDidLoad()
            self.tableView.reloadData()
        }
        
        func spanishLanguage () {
            appLanguage = "es"
            userForeignLanguage = true
            NotificationCenter.default.post(name: Notification.Name(rawValue: languageChangedKey), object: self)
            self.viewDidLoad()
            self.tableView.reloadData()
        }
        
        func russianLanguage () {
            appLanguage = "ru"
            userForeignLanguage = false
            NotificationCenter.default.post(name: Notification.Name(rawValue: languageChangedKey), object: self)
            self.viewDidLoad()
            self.tableView.reloadData()
        }
        
        func chineseLanguage () {
            appLanguage = "zh-Hans"
            userForeignLanguage = false
            NotificationCenter.default.post(name: Notification.Name(rawValue: languageChangedKey), object: self)
            self.viewDidLoad()
            self.tableView.reloadData()
        }
    

    I set a breakpoint at each language func, but the action is not even calling the func when selected in the popup menu.

    Have no idea how to solve this on my own and hope that you can upload an updated version.

    Thank you, David

    opened by xs6615 4
  • Add SPM Support

    Add SPM Support

    Before submitting issues ...

    • Make sure you are using XLActionController latest release or master branch version.
    • Make sure your Xcode version is the latest stable one.
    • Check if the issue was already reported or fixed. 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".

    When submitting issues, please provide the following information to help maintainers to fix the problem faster:

    • Environment: XLActionController, Xcode and iOS version you are using.
    • In case of reporting errors, provide Xcode console output of stack trace or code compilation error.
    • Any other additional detail such as example code that you think it would be useful to understand, reproduce and solve the problem.
    opened by Ganesh623 4
  • SPM new issues with Xcode 13.0

    SPM new issues with Xcode 13.0

    Importing XLActionController release 5.1.0 with Swift Package Manager on Xcode 13.0

    I get these warnings :

    found 1 file(s) which are unhandled; explicitly declare them as resources or exclude from the target
    /Users/vincent/Library/Developer/Xcode/DerivedData/YoubooxApp-gepbqhkkvarnsgehvdaxymsrqjuw/SourcePackages/checkouts/XLActionController/Source/Info.plist
    

    and Invalid Resource 'Resource/ActionCell.xib': File not found.

    Could you please update package.swift to resolve them ?

    opened by vince4 1
  • In the Spotify style, the Cancel button obscures the following option

    In the Spotify style, the Cancel button obscures the following option

    Hello, I like the XLActionController you made very much, but I found a problem during using it. I opened the Example Project downloaded from GitHub and ran the Spotify example file. I noticed that the Cancel button blocked the options behind it and I had to scroll up the view to see the options below, which was different from the demo GIF. I also had this problem when I was writing code myself.I didn't know how to solve the problem.

    I'm using Xcode version 12.5 and XlActionController version 5.1 simulator_screenshot_F5F09621-2751-439D-82A5-E9414F3BBFA3

    opened by Jackmaliao 1
  • Is there a way to remove cancel button animation?

    Is there a way to remove cancel button animation?

    I like to use and customise the Tweetbot example, but I didn't manager to stop the bounce animation on the cancel button. My goal is just the native look with detail label. I tried to set to false the bounces property, but it's still here.

    opened by elanovasconcelos 0
  • Message from debugger: Terminated due to signal 9

    Message from debugger: Terminated due to signal 9

    I am receiving this error on

    Message from debugger: Terminated due to signal 9

    Spotify Tweetbot Twitter Youtube Periscope

    only working on Skype

    opened by shadyk 0
  • cover safe areas

    cover safe areas

    In iPhone X and above, it shows background on the bottom(in case of YoutubeActionController) because of safe areas. How to cover that up? I am opening this in a custom view in tabbar controller

    opened by singh-karan-7 0
  • Where to place code to 'show more options'

    Where to place code to 'show more options'

    My twitter style popup displays a list of 10 items pulled from a 'paged' api. If one the 10 is not the right one then my app needs to show the next 10 items, this is done by querying the API again for page 2. Where is the best place to put this code?

    opened by netsmith 3
  • Corrected counting contentHeight in ActionController

    Corrected counting contentHeight in ActionController

    Hi 👋

    I noticed if calculated contentHeight in ActionController, we didn't use collectionView.contentInset.bottom. I think it's not correct. For example, you can see DynamicsActionController that it uses collectionView.contentInset.bottom for calculate contentHeight.

    But both this class use setUpContentInsetForHeight. So, now var topInset = height - contentHeight - safeAreaInsets.bottom (for ActionController) ignore collectionView.contentInset.bottom and the alert attache to SafeArea without a inset.

    I tried to fix it. 🙃

    opened by Puasonych 0
  • How to disable auto rotate

    How to disable auto rotate

    i set Device Orientation is Portrait , but when the XLActionController show , it can auto rotate , i use PeriscopeActionController style , but PeriscopeActionController is not open class , i can't override it, i must add these code to class ActionController:

     override open var supportedInterfaceOrientations: UIInterfaceOrientationMask{
            get{
                return .portrait
            }
        }
    
    opened by boboxiaodd 0
  • Periscope add safearea subview

    Periscope add safearea subview

    i use these code:

    let bottomPadding = UIApplication.shared.keyWindow!.safeAreaInsets.bottom
            if  bottomPadding > 0 {
                print("\(actionController.collectionView.bounds.height) \(UIScreen.main.bounds.height) \(bottomPadding)")
                let bottomView = UIView(frame: CGRect(x: 0.0,
                                                      y: actionController.collectionView.bounds.height - bottomPadding - 5.0,
                                                      width: UIScreen.main.bounds.width,
                                                      height: bottomPadding + 5.0))
                bottomView.backgroundColor = .white
                actionController.collectionView.backgroundView?.addSubview(bottomView)
            }
    
    opened by boboxiaodd 0
  • a layout bug in Spotify action controller

    a layout bug in Spotify action controller

    I found a layout issue in Spotify's action controller. you can see it if you run the example on iPhone 11 Pro in simulator and in section Spotify also I'll send a screenshot for more info info: the "Start radio" button is under cancel button.

    Screen Shot 2019-10-11 at 8 29 00 PM bug 
    opened by SalarDastan 2
Releases(5.1.0)
Owner
xmartlabs
xmartlabs
Highly customizable Action Sheet Controller with Assets Preview written in Swift

PPAssetsActionController Play with me ▶️ ?? If you want to play with me, just tap here and enjoy! ?? ?? Show me ?? Try me ?? The easiest way to try me

Pavel Pantus 71 Aug 7, 2021
A Swift library to provide a bouncy action sheet

Hokusai is a Swift library that provides a bouncy action sheet. It will give the users a fancy experience without taking pains coding the cool animati

Yuta Akizuki 430 Nov 28, 2021
A fully customizable container view controller to display a set of ViewControllers in a horizontal scroll view. Written in Swift.

DTPagerController This is a control for iOS written in Swift. DTPagerController is simple to use and easy to customize. Screenshots Default segmented

Tung Vo 285 Dec 30, 2021
A Powerful , Extensible CSS Parser written in pure Swift.

A Powerful , Extensible CSS Parser written in pure Swift. Basic Usage From CSS: #View { "width" : 118; "height" : 120.5; "color1" : "#888888"; "co

null 269 Jan 9, 2022
MZFormSheetPresentationController provides an alternative to the native iOS UIModalPresentationFormSheet, adding support for iPhone and additional opportunities to setup UIPresentationController size and feel form sheet.

MZFormSheetPresentationController MZFormSheetPresentationController provides an alternative to the native iOS UIModalPresentationFormSheet, adding sup

Michał Zaborowski 976 Jan 7, 2022
Former is a fully customizable Swift library for easy creating UITableView based form.

Former is a fully customizable Swift library for easy creating UITableView based form. Submitting Issues Click HERE to get started with filing a bug r

Ryo Aoyama 1.3k Dec 28, 2021
Spreadsheet CollectionViewLayout in Swift. Fully customizable. 🔶

SwiftSpreadsheet Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Swift 5.0 Inst

Wojtek Kordylewski 622 Dec 30, 2021
Fully customizable Facebook reactions like control

Reactions is a fully customizable control to give people more ways to share their reaction in a quick and easy way. Requirements • Usage • Installatio

Yannick Loriot 578 Dec 15, 2021
A beautiful radar view to show nearby items (users, restaurants, ...) with ripple animation, fully customizable

HGRippleRadarView Example To run the example project, clone the repo, and run pod install from the Example directory first. This project is inspired b

Hamza Ghazouani 327 Dec 10, 2021
A fully customizable popup style menu for iOS 😎

Guide Check out the documentation and guides for details on how to use. (Available languages:) English 简体中文 What's a better way to know what PopMenu o

Cali Castle 1.3k Jan 5, 2022
A controller that uses a UIStackView and view controller composition to display content in a list

StackViewController Overview StackViewController is a Swift framework that simplifies the process of building forms and other static content using UIS

Seed 856 Dec 21, 2021
UIMenuItem with image and closure(block) action

MenuItemKit MenuItemKit provides image and block(closure) support for UIMenuItem. MenuItemKit is a Swift project but Objective-C is supported without

Realazy Xian-an CHEN 818 Dec 26, 2021
:heart: Floating Action Button for iOS

Floaty Floaty is simple floating action button for iOS. (formerly KCFloatingActionButton) Why change the name? Follow the swift naming convention. KCF

Lee Sun-Hyoup 1.4k Dec 30, 2021
Paging view controller with customizable menu in Swift

This library is inspired by PageMenu Updates See CHANGELOG for details Description Standard mode with flexible item width Segmented control mode Infin

Yusuke Kita 2.5k Dec 29, 2021
:octocat: Gliding Collection is a smooth, flowing, customizable decision for a UICollectionView Swift Controller. iOS library made by @Ramotion

GLIDING COLLECTION A smooth, flowing, customizable decision for a UICollectionView Swift Controller We specialize in the designing and coding of custo

Ramotion 1.5k Dec 30, 2021
🔍 Awesome fully customize search view like Pinterest written in Swift 5.0 + Realm support!

YNSearch + Realm Support Updates See CHANGELOG for details Intoduction ?? Awesome search view, written in Swift 5.0, appears search view like Pinteres

Kyle Yi 1.2k Jan 10, 2022
A paging view controller with a highly customizable menu ✨

Getting Started | Customization | Installation Features Parchment lets you page between view controllers while showing any type of generic indicator t

Martin Rechsteiner 2.8k Dec 31, 2021
A simple and easy to use view controller enabling you to enter a phone number with a country code similar to WhatsApp written in Swift

PhoneNumberPicker A simple and easy to use view controller enabling you to enter a phone number with a country code similar to WhatsApp Screenshots In

Hugh Bellamy 144 Dec 2, 2021