A high-performance button control with rounded corners for iOS.

Overview

TORoundedButton

TORoundedButton

CI Version SwiftPM compatible Carthage compatible GitHub license Platform

TORoundedButton is an open source UI control of a standard user button. Its design consists of displaying text on top of a solid rectangle with rounded corners. This UI style has started becoming more and more common in iOS 11 and above, and while Apple has an official one they use internally, it is not possible to achieve this effect without heavily customizing UIButton.

TORoundedButton has been crafted to be as graphically performant as possible, based on guidance from Core Animation engineers from Apple at WWDC 2019. It is not simply a subclass of UIButton. Instead, it is a subclass of UIControl with all button graphics and behavior re-engineered from scratch.

Features

  • A completely custom implementation; no UIButton hacking.
  • Implemented with guidance from Core Animation engineers at WWDC 2019.
  • Uses the classic Apple 'continuous' curving style on iOS 13 and up.
  • Extremely flexible with many options for configuring the look and feel of the button.
  • Integrates with Interface Builder for visual configuration.
  • Elegantly cancels and resumes animations when the user slides their finger on and off the button.
  • Piggy-backs off most standard UIView properties in order to minimize the learning curve.
  • Includes dynamic color code to generate a 'tapped' shade of the normal color, saving you extra effort.
  • Fully compatible with Swift, with the class name RoundedButton.

Examples

TORoundedButton features a complete default configuration useful for most app instances, but can be easily modified beyond that.

// Create a new instance of `RoundedButton`
let button = RoundedButton(text: "Continue")

// The button color itself is controlled via tintColor
button.tintColor = .red

// If desired a brightness offset that will be used to 
// dynamically calculate the 'tapped' color from the default one.
button.tappedTintColorBrightnessOffset = -0.15

// A closure is used to detect when tapped
button.tappedHandler = {
	print("Button tapped!")
}

One important thing to remember is that the button color is controlled via tintColor and not backgroundColor.

Requirements

TORoundedButton will work with iOS 10 and above. While written in Objective-C, it will easily import into Swift.

Manual Installation

Copy the contents of the TORoundedButton folder to your app project.

CocoaPods

pod 'TORoundedButton'

Carthage

github "TimOliver/TORoundedButton"

Why build this?

This sort of button style is more or less the bread and butter of a lot of iOS apps. But even that being the case, it is not offered as an officially supported style of UIButton.

Because of this, most developers will achieve this look by simply giving a UIButton a solid background, and then using the Core Animation cornerRadius API to round the corners.

This sort of "just-in-time" solution is fine for the vast majority of apps out there that might need one or two rounded buttons. But certainly for apps that would want many of these buttons, and demand that look and behaviour is consistent, then it's a no-brainer to create a standardised library for this style.

In addition to that, while UIButton is a vary capable API, it is quite limiting. For example, it's not possible to animate the button zooming as it is tapped, or any other custom behaviour.

As such, in order to give this control as much control and flexibility over UIButton, it made sense to simply subclass UIControl to get all of the system interaction features, and then custom tailor the visual look on top of it.

Feedback from Apple

During WWDC, it's usually possible to visit Apple engineers in the labs to get 1-on-1 engineering consultations. In 2019, this library was shown directly to two engineers from the Core Animation team, and they were exceptionally helpful in clearing up some misconceptions this library had assumed.

Some of the tips they mentioned included:

  1. The original codepath this library used where it generated an opaque background in Core Graphics was basically an anti-pattern. The memory consumption and CPU overhead of creating these bitmaps almost certainly outweighed the performance gains over simply using the cornerRadius API.
  2. Core Animation is very smart in that if no subview content will be clipped, it uses Metal to draw the cornerRadius clipping as a transparent bitmap. Transparent blending is basically free on modern iOS devices, so this is much more preferable to using an opaque bitmap from Core Graphics.
  3. If there is subview content that might be clipped, Core Animation must do an off-screen render pass (This can be tested in the Simulator by checking "Off-screen rendered"). While doing this occasionally is fine, it is still a much heavier graphics operation than regular transparency blending and should always be avoided if it can be helped.

Credits

TORoundedButton was created by Tim Oliver as a component of iComics.

iOS device mockup art by Pixeden.

License

TORoundedButton is available under the MIT license. Please see the LICENSE file for more information. analytics

Comments
  • Set titleLabel's backgroundColor on tintColorDidChange

    Set titleLabel's backgroundColor on tintColorDidChange

    When initializing a TORoundedButton in the following way:

    let button = RoundedButton(text: "I agree")
    button.tintColor = UIColor.appPurple
    button.textColor = .white
    button.backgroundColor = .white
    button.cornerRadius = 4
    

    This is the result:

    RoundedButton

    Tapping on the button makes this glitch go away, because self.titleLabel.backgroundColor = self.isTapped ? [UIColor clearColor] : self.tintColor; is called.

    This PR sets the titleLabel's backgroundColor on layoutSubviews to avoid this bug.

    opened by natanrolnik 6
  • Carthage build end up in /static folder?

    Carthage build end up in /static folder?

    While every other framework builds directly into the build folder, somehow this framework ends up in the build/static folder. Any way it can be consistent with others? Thanks!

    Screen Shot 2019-06-15 at 1 01 48 PM enhancement 
    opened by danqing 5
  • Swift Package Manager error

    Swift Package Manager error

    While trying to install the library using Swift Package Manager in Xcode, I get an error.

    TORoundedButton has no Package.swift manifest for version 1.1.2

    Screenshot 2020-02-13 at 23 17 12 bug help wanted 
    opened by marcheimendinger 4
  • Question regarding a standard approach

    Question regarding a standard approach

    I have been generating rounded-stretchable images for years (dynamically, with code) to set as the backgroundImage of my UIButtons to the same goal as your library.

    This also has the advantage that I get highlight-colorization for free.

    It wasn't clear after reading your README why I should instead use your library.

    Thanks for your time!

    opened by mxcl 3
  • Why it performance better than UIButton?

    Why it performance better than UIButton?

    I saw this in the readme

    most developers will achieve this look by simply giving a UIButton a solid background, and then using the Core Animation cornerRadius API to round the corners.

    As simple as this is, this is gross overkill for a lot of circumstances in which you'd use a buttonI

    In the implementation, I saw cornerRadius API

    - (void)setCornerRadius:(CGFloat)cornerRadius
    {
        // Make sure the corner radius doesn't match
        if (fabs(cornerRadius - _cornerRadius) < FLT_EPSILON) {
            return;
        }
        
        _cornerRadius = cornerRadius;
        self.backgroundView.layer.cornerRadius = _cornerRadius;
        [self setNeedsLayout];
    }
    

    So what's the difference? please help me out

    question 
    opened by huahuahu 2
  • Inactive when inside UICollectionViewCell

    Inactive when inside UICollectionViewCell

    I don't know what may be the cause yet, but what I see is that if I use RoundedButton (Swift) inside UICollectionViewCell (added to contentView), it doesn't handle any action. If I switch to UIButton the same addTarget:... start working, this is why I suspect there is maybe something missing in this component.

    I use RoundedButton in other places and it works just fine ;)

    I really can't explain this behavior more at this point, I'm sorry.

    bug 
    opened by krzyzanowskim 2
  • Set alpha when disabling button

    Set alpha when disabling button

    I noticed that calling the roundedButton.isEnabled = false doesn't dim it - which is the case in other UIControls.

    I noticed that in all setters _isDirty = YES; [self setNeedsLayout]; are called, and thought about using the same pattern; however, there is no need to layout all the subviews again, so I thought setting alpha directly a more reasonable solution.

    opened by natanrolnik 2
  • Subtitle:  Trivial code change to allow the button title to be multiple lines of text.

    Subtitle: Trivial code change to allow the button title to be multiple lines of text.

    Trivial code change allows me to set the button title to a string that contains two lines of text. Example:

    let button = RoundedButton() button.attributedText = NSAttributedString(string: "Line 1\nLine2)

    See issue #39

    opened by ehmjaysee 1
  • Tapping the button sends the gesture to the responder below

    Tapping the button sends the gesture to the responder below

    I have added a UITapGestureRecognizer to my UIViewController's view and noticed that tapping on the RoundedButton embedeed in that view is also registered by the gesture recognizer. I don't think it's a desired effect

    question 
    opened by wiencheck 1
  • Implement proper vertical text alignment

    Implement proper vertical text alignment

    At the moment, the text label in the middle of the button is aligned by simply centering the UILabel in the very middle of the super view.

    However, depending on the actual text in the label, depending if the text has any characters with a descender (eg, p or y ), it's possible two buttons lined up would have different vertical alignments of their buttons.

    Depending on how UILabel works, this might not be necessary, but just in case, I'll be checking to see if I need to include extra vertical alignment math to properly center the labels.

    Stack Overflow reference: https://stackoverflow.com/questions/41981675/in-swift-how-to-get-the-y-position-of-a-text-baseline-of-a-uilabel

    enhancement 
    opened by TimOliver 1
  • When disabling, set containerView alpha (and not button's alpha itself)

    When disabling, set containerView alpha (and not button's alpha itself)

    This one is actually a better implementation of #15 - It makes more sense to set the containerView's alpha instead of the whole view's alpha.

    What do you think, @TimOliver ?

    opened by natanrolnik 1
  • Are you interested in a Swift port of this button?

    Are you interested in a Swift port of this button?

    Hi @TimOliver

    I love your simple, but powerful implementation of this kind of button - exactly what I need for my apps. I ported this library to Swift 5 - along with the unit tests and the sample app.

    If you are interested, I could add you as a collaborator to my private repo, you could have a look, and if you like it, maybe you'd like to release it alongside your Objective-C implementation.

    Cheers, Peter

    opened by psalzAppDev 2
  • How to set transparent background with text?

    How to set transparent background with text?

    I noticed a strange behavior when setting colors for the button. What I'm doing is simply

                button.tintColor = theme.primary.withAlphaComponent(0.2)
                button.textColor = theme.primary
    

    and label ends up with a strange frame behind it. See the screenshot IMG_0403

    bug help wanted good first issue 
    opened by wiencheck 1
Releases(1.1.3)
  • 1.1.3(Dec 12, 2020)

  • 1.1.2(Jul 7, 2019)

  • 1.1.1(Jun 21, 2019)

    Enhancements

    • Added unit tests to check consistent initial behaviour. (#22)
    • Updated the documentation in the header to match expected default values. (#22)

    Fixed

    • A bug where the dynamic text size would not properly restore. (#22)
    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Jun 21, 2019)

    Enchancements

    • Added minimumWidth property to help with guiding external layout. (#21)
    • Refactored button from Core Animation labs chat at WWDC 2019. (#20)
    • Increased corner radius default value to 12.0. (#20)
    • Added lower alpha value when button is set to disabled. (#15)
    • Added UIControlEventPrimaryActionTriggered event handling for iOS 9 apps relying on that action. (#13)
    • Added attributed string support to button. (#11)

    Fixed

    • A bug where the label's background color sometimes didn't match the button tint color. (#14)
    • Renamed framework project name to fix IB render crash. (#20)
    Source code(tar.gz)
    Source code(zip)
  • 1.0.0(Apr 30, 2019)

Owner
Tim Oliver
Gamer. Developer. Geek. Senior Software Engineer at @Drivemode (prev. @Realm). Lover of writing iOS code and singer of bad karaoke. æ—„æœŹèȘžă‚‚ă‚Șăƒƒă‚±ă€œ
Tim Oliver
Revamped Download Button. It's kinda a reverse engineering of Netflix's app download button.

NFDownloadButton Revamped Download Button Requirements Installation Usage License Requirements iOS 8.0+ Swift 4.2+ Xcode 10.0+ Installation CocoaPods

Leonardo Cardoso 433 Nov 15, 2022
Floaty is simple floating action button for iOS.

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

Lee Sun-Hyoup 1.5k Jan 7, 2023
iOS Pod for a Soft UI (Neumorphic) Button for UIKit written in Swift

iOS Pod for a Soft UI (Neumorphic) Button for UIKit written in Swift

Pallav Agarwal 21 Oct 23, 2022
iOS 7-style bouncy button.

SSBouncyButton SSBouncyButton is simple button UI component with iOS 7-style bouncy animation. Take A Look Try It! pod 'SSBouncyButton', '~> 1.0' Use

StyleShare 310 Dec 15, 2022
Flat design pressable button for iOS developers.

HTPressableButton HTPressableButton is designed for iOS developers to be able to spend time developing ideas, not building basic buttons. These stylis

Famolus 859 Dec 12, 2022
Interactive and fully animated Material Design button for iOS developers.

WYMaterialButton Inspired by Google Material Design, written purely in Swift 3. WYMaterialButton implemented Material Design on iOS and add more dynam

Yu Wang 76 Oct 7, 2022
Cute Animated Button written in Swift.

DOFavoriteButton Cute Animated Button written in Swift. It could be just right for favorite buttons! Requirements iOS 7.0+ Swift 1.2 Installation Cart

Daiki Okumura 3.6k Dec 29, 2022
Customizable and easy to use expandable button in Swift.

ExpandableButton Requirements iOS 9.0+ Installation CocoaPods: Add the following line to your Podfile: pod 'ExpandableButton' #for swift less than 4.

Dmytro Mishchenko 98 Dec 5, 2022
Easily customizable floating button menu created with SwiftUI

FloatingButton Easily customizable floating button menu created with SwiftUI We are a development agency building phenomenal apps. Usage Create main b

Exyte 715 Dec 30, 2022
IGStoryButtonKit provides an easy-to-use button with rich animation and multiple way inspired by instagram story/stories.

Introduction Have you ever seen UI like instagram story, haven't you? Actually, features like instagram story have been implemented in many applicatio

mutation 34 Nov 8, 2022
LTHRadioButton - A radio button with a pretty animation

LTHRadioButton Slightly inspired by Google's material radio button. The clip below has 3 sections: full speed, 25% and 10%, but after converting it to

Roland Leth 368 Dec 16, 2022
Multiple state tap-to-toggle UIButton (like old camera flash button)

Multiple State Toggle UIButton A UIButton subclass that implements tap-to-toggle button text. (Like the camera flash and timer buttons) Usage Just cre

Yonat Sharon 83 Oct 11, 2022
Lickable-Button We made the buttons on the screen look so good you'll want to lick them

Lickable-Button We made the buttons on the screen look so good you'll want to lick them. - Steve Jobs A little SwiftUI button project at WWDC 2021 Lic

Nate Thompson 14 Dec 29, 2021
Craft that perfect SwiftUI button effect đŸ‘ŒđŸŒ

buttoncraft (SwiftUI 3.0 App) Experimenting with SwiftUI 3.0 whilst creating a practical app to craft that perfect button style. ✈ Testflight https:/

An Trinh 188 Dec 28, 2022
Custom loading button with progress swiftui

CustomLoadingButton Simple Custom Loading Progress Button for SwiftUI Version 1.0.0 This version requires Xcode 11+ SwiftUI iOS 13+ macOS 10.15+ Insta

Tariqul 1 Dec 14, 2022
An open-source library to use with SwiftUI, It allows you to create Floating menu action button.

Floating Menu Action Button Example Overview This is an open-source library to use with SwiftUI. It allows you to create Floating menu action button. Ins

ugo 3 Aug 19, 2022
Flat button with 9 different states using POP

VBFPopFlatButton Flat button with 21 different states and 2 types animated using pop. These are some examples of both types in different states: And h

Victor Baro 3.1k Nov 30, 2022
Material Design Floating Action Button in liquid state

LiquidFloatingActionButton [] (https://github.com/Carthage/Carthage) LiquidFloatingActionButton is floating action button component of material design

Takuma Yoshida 3.8k Dec 29, 2022
Simple and customizable button in Swift

SwiftyButton Maintainer(s): @nickm01 @pmacro @aryamansharda Simple and customizable button in Swift. Installation Cocoapods pod 'SwiftyButton' Cartha

Scoop 542 Dec 13, 2022