0

BButton 2.0 for iOS

-

Twitter Bootstrap (v2.3.1) Buttons for iOS.

Refactored and refined from mattlawer/BButton.

GitHub

0

DDExpandableButton for iOS

-
Full

A single-file iOS3+ class designed to be used like an expandable UIButton ; as seen in the iOS Camera app for the "flash" button.

 

GitHub

0

Non-Rectangular Button Shapes

-

Ole Begemann has created an interesting control for creating non-rectangular shaped buttons, OBShapedButton. Although UIButton can use images of various shapes, one key benefit of OBShapedButton is that a button of this type will only respond to touches in the areas of the button image that is visible.

The demo project included shows how OBShapedButton differs from a standard button, as the figure below indicates:

OBShapedButton also supports complex image shapes:

Download OBShapedButton

You can download OBShapedButton from github.

0

Fun With UIButtons and Core Animation Layers

-

 

 

Upon first glance, the UIButton class doesn’t seem to provide what you might expect in terms of customization. This often causes developers to resort to creating buttons in an image editor and then specifying that in the Background field in Interface Builder. This is a fine solution and will likely give you what you need, but with Core Animation layers there is a simpler way to achieve the look you want without having to create an image. This post will demonstrate how.

Setting a Background Color

Solid Background Buttons

In Interface Builder, you can specify a background color for your button if you are using the ‘Custom’ button setting, but when you run the application, the button will display as a block with no rounded corners. This is because custom buttons don’t really have any default attributes defined. It’s completely up to you to define them. Core Animation layers can help.

Note: Before I get into the source code, I want to remind you that you’ll need to add the QuartzCore framework to your project and #import <QuartzCore/QuartzCore.h> into one of your header files to have Core Animation layer support. I normally add this import statement to my precompiled header (.pch) file.

What Interface Builder doesn’t give you, you can still take advantage of by writing a little bit of code. For example, if you want your custom button to have a red background color with rounded corners and a border, you need to define an outlet in your view controller where the button will be referenced and set the following attributes on the UIButton’s layer.

  1. [[button1 layer] setCornerRadius:8.0f];
  2. [[button1 layer] setMasksToBounds:YES];
  3. [[button1 layer] setBorderWidth:1.0f];
[[button1 layer] setCornerRadius:8.0f];
[[button1 layer] setMasksToBounds:YES];
[[button1 layer] setBorderWidth:1.0f];

With this code the layer gets a corner radius of 8.0 and the -setMasksToBounds: tells the button’s layer to mask any layer content that comes below it in the layer tree. This is necessary in order for the layer to mask off the rounded corners.

Finally, set the border width to 1.0 to display an outline around the button. The default color for this border is black. You can change it to anything you like using -setBorderColor: on the layer passing it a CGColorRef (e.g. [[UIColor greenColor] CGColor] would give you a green border).

iPhone Development Protip: Rounding corners is possible on any UIView based view. All UIViews have a root layer. You simply call -setCornerRadius: and -setMasksToBounds: on the view’s layer and your corners will be rounded. It is that simple.

You can set the background color in Interface Builder or in code–whichever you prefer. There are two ways to do this in code. One using the layer and one using the UIView call to -setBackgroundColor:.

  1. // Core Animation way
  2. [[button1 layer] setBackgroundColor:[[UIColor redColor] CGColor]];
  3. // UIView way
  4. [button1 setBackgroundColor:[UIColor redColor]];
// Core Animation way
[[button1 layer] setBackgroundColor:[[UIColor redColor] CGColor]];
// UIView way
[button1 setBackgroundColor:[UIColor redColor]];

The main difference between the two is that the layer works with a CGColorRef while the UIView works with a UIColor. It’s a subtle difference, but one that you should know.

Gradient Buttons Rule

Colorful Buttons App

The demo app uses some ultra-bright gaudy looking color gradients just for effect. I suggest you don’t use something so loud and obnoxious. A more subtle difference between colors will look better. Of course this is subjective, so do what you like.

To achieve this gradient look, I use a CAGradientLayer and add it to the root of the button’s layer tree. In fact, for the demo application, I created a UIButton derived class that encapsulates the gradient layer creation and drawing. Here is its implementation:

  1. #import "ColorfulButton.h"
  2.  
  3. @implementation ColorfulButton
  4.  
  5. @synthesize _highColor;
  6. @synthesize _lowColor;
  7. @synthesize gradientLayer;
  8.  
  9. - (void)awakeFromNib;
  10. {
  11.     // Initialize the gradient layer
  12.     gradientLayer = [[CAGradientLayer alloc] init];
  13.     // Set its bounds to be the same of its parent
  14.     [gradientLayer setBounds:[self bounds]];
  15.     // Center the layer inside the parent layer
  16.     [gradientLayer setPosition:
  17.                 CGPointMake([self bounds].size.width/2,
  18.                        [self bounds].size.height/2)];
  19.  
  20.     // Insert the layer at position zero to make sure the
  21.     // text of the button is not obscured
  22.     [[self layer] insertSublayer:gradientLayer atIndex:0];
  23.  
  24.     // Set the layer's corner radius
  25.     [[self layer] setCornerRadius:8.0f];
  26.     // Turn on masking
  27.     [[self layer] setMasksToBounds:YES];
  28.     // Display a border around the button
  29.     // with a 1.0 pixel width
  30.     [[self layer] setBorderWidth:1.0f];
  31.  
  32. }
  33.  
  34. - (void)drawRect:(CGRect)rect;
  35. {
  36.     if (_highColor && _lowColor)
  37.     {
  38.         // Set the colors for the gradient to the
  39.         // two colors specified for high and low
  40.         [gradientLayer setColors:
  41.                      [NSArray arrayWithObjects:
  42.                             (id)[_highColor CGColor],
  43.                             (id)[_lowColor CGColor], nil]];
  44.     }
  45.     [super drawRect:rect];
  46. }
  47.  
  48. - (void)setHighColor:(UIColor*)color;
  49. {
  50.     // Set the high color and repaint
  51.     [self set_highColor:color];
  52.     [[self layer] setNeedsDisplay];
  53. }
  54.  
  55. - (void)setLowColor:(UIColor*)color;
  56. {
  57.     // Set the low color and repaint
  58.     [self set_lowColor:color];
  59.     [[self layer] setNeedsDisplay];
  60. }
  61.  
  62. - (void)dealloc {
  63.     // Release our gradient layer
  64.     [gradientLayer release];
  65.     [super dealloc];
  66. }
  67. @end
#import "ColorfulButton.h"

@implementation ColorfulButton

@synthesize _highColor;
@synthesize _lowColor;
@synthesize gradientLayer;

- (void)awakeFromNib;
{
    // Initialize the gradient layer
    gradientLayer = [[CAGradientLayer alloc] init];
    // Set its bounds to be the same of its parent
    [gradientLayer setBounds:[self bounds]];
    // Center the layer inside the parent layer
    [gradientLayer setPosition:
                CGPointMake([self bounds].size.width/2,
                       [self bounds].size.height/2)];

    // Insert the layer at position zero to make sure the
    // text of the button is not obscured
    [[self layer] insertSublayer:gradientLayer atIndex:0];

    // Set the layer's corner radius
    [[self layer] setCornerRadius:8.0f];
    // Turn on masking
    [[self layer] setMasksToBounds:YES];
    // Display a border around the button
    // with a 1.0 pixel width
    [[self layer] setBorderWidth:1.0f];

}

- (void)drawRect:(CGRect)rect;
{
    if (_highColor && _lowColor)
    {
        // Set the colors for the gradient to the
        // two colors specified for high and low
        [gradientLayer setColors:
                     [NSArray arrayWithObjects:
                            (id)[_highColor CGColor],
                            (id)[_lowColor CGColor], nil]];
    }
    [super drawRect:rect];
}

- (void)setHighColor:(UIColor*)color;
{
    // Set the high color and repaint
    [self set_highColor:color];
    [[self layer] setNeedsDisplay];
}

- (void)setLowColor:(UIColor*)color;
{
    // Set the low color and repaint
    [self set_lowColor:color];
    [[self layer] setNeedsDisplay];
}

- (void)dealloc {
    // Release our gradient layer
    [gradientLayer release];
    [super dealloc];
}
@end


Now, when I’m creating a button in Interface Builder, I can make it of classColorfulButton and then set an outlet for it in my view controller.

If I don’t set colors for a gradient, it will just render the button using the background color I specify for it in Interface Builder. If, however, I want to take advantage of the gradient capability, I set the gradient colors in my view controller as shown in the following code snippet:

  1. - (void)viewDidLoad {
  2.     [super viewDidLoad];
  3.  
  4.     [button1 setHighColor:[UIColor redColor]];
  5.     [button1 setLowColor:[UIColor orangeColor]];
  6.  
  7.     [button2 setHighColor:[UIColor blueColor]];
  8.     [button2 setLowColor:[UIColor lightGrayColor]];
  9.  
  10.     [button3 setHighColor:[UIColor yellowColor]];
  11.     [button3 setLowColor:[UIColor purpleColor]];
  12.  
  13.     [button4 setHighColor:[UIColor cyanColor]];
  14.     [button4 setLowColor:[UIColor magentaColor]];
  15. }
- (void)viewDidLoad {
    [super viewDidLoad];

    [button1 setHighColor:[UIColor redColor]];
    [button1 setLowColor:[UIColor orangeColor]];

    [button2 setHighColor:[UIColor blueColor]];
    [button2 setLowColor:[UIColor lightGrayColor]];

    [button3 setHighColor:[UIColor yellowColor]];
    [button3 setLowColor:[UIColor purpleColor]];

    [button4 setHighColor:[UIColor cyanColor]];
    [button4 setLowColor:[UIColor magentaColor]];
}


These are the first four buttons you see in the demo app screenshot above. The buttons are declared in the view controller header as show in the following snippet:

  1. #import <UIKit/UIKit.h>
  2. #import "ColorfulButton.h"
  3.  
  4. @interface ColorfulButtonsViewController : UIViewController {
  5.     IBOutlet ColorfulButton *button1;
  6.     IBOutlet ColorfulButton *button2;
  7.     IBOutlet ColorfulButton *button3;
  8.     IBOutlet ColorfulButton *button4;
  9. }
  10. @end
#import <UIKit/UIKit.h>
#import "ColorfulButton.h"

@interface ColorfulButtonsViewController : UIViewController {
    IBOutlet ColorfulButton *button1;
    IBOutlet ColorfulButton *button2;
    IBOutlet ColorfulButton *button3;
    IBOutlet ColorfulButton *button4;
}
@end


The CAGradientLayer supports adding an array of colors and will automatically render them linearly with equal distribution. It will also allow you to specify the distribution pattern, however, to keep it simple here I just use two colors represented by the upper color called highColor and the lower color called lowColor. If you want to add more complex gradients, you could modify my ColorfulButtonclass to take an array of colors as well. I leave this as an exercise for the reader.

Conclusion

Next time you need to customize a button, consider using Core Animation layers first. You may be surprised at what all you can achieve without having to resort to creating images to use as the button background. I have included the source code for this blog post below. Let me know if you have any thoughts or questions about it in the comments section. Until next time.

 

Cocoa Is My Girlfriend » Fun With UIButtons and Core Animation Layers.