Alternative Button
There must be a time when every iOS developer wanted to place the image of UIButton above the title. Alternative Button is here for that!
There must be a time when every iOS developer wanted to place the image of UIButton
above the title. Alternative Button is here for that!
TL;DR
Alternative Button is available as a pod. You can easily add it to your project just by adding pod ‘AlternativeButton’
to your ‘Podfile’ and running pod install
in your project directory.
Also you can find both Alternative Button and the example project here.
Structure
Alternative Button is a subclass of UIButton
and just by overriding a few methods and a few additions, it presents its image above the title. And thanks to a new feature of Xcode 6, it can be previewed in Interface Builder. Also corner radius of its image view can be set from Attributes Inspector too.
Layout
By overriding -layoutSubviews
method of UIView
, we can interfere with the view hierarchy and layout of any subview of a view. So we did:
self.imageView.frame =
(CGRect){.origin = (CGPoint){.x = margin,
.y = margin},
.size = (CGSize){.width = imageViewWidth,
.height = imageViewWidth}};
self.imageView.center =
(CGPoint){.x = CGRectGetWidth(self.frame) / 2.0,
.y = imageViewWidth / 2.0 + margin};
[self.titleLabel sizeToFit];
self.titleLabel.frame =
(CGRect){.origin = (CGPoint){.x = margin,
.y = imageViewWidth + 2 * margin},
.size = self.titleLabel.frame.size};
self.titleLabel.center =
(CGPoint){.x = CGRectGetWidth(self.frame) / 2.0,
.y = CGRectGetHeight(self.frame) - CGRectGetHeight(self.titleLabel.frame) / 2.0 - margin};
imageViewWidth
is a constant defined in the class and its value is64.0
Here we just adjust the frames of both image view and the title label. We place them vertically in line and horizontally centered.
Size
-intrinsicContentSize
method of UIView
returns a CGSize
indicating the desired size of itself. So we must override this too, like so:
[self.titleLabel sizeToFit];
CGFloat titleLabelWidth = CGRectGetWidth(self.titleLabel.frame) + margin * 2; // margin from both sides.
CGFloat imageViewWidth = CGRectGetWidth(self.imageView.frame) + margin * 2; // margin from both sides.
CGFloat height = CGRectGetHeight(self.imageView.frame) + CGRectGetHeight(self.titleLabel.frame) + margin * 3; // margin from top and bottom and distance between `imageView` and `titleLabel`.
return CGSizeMake(MAX(titleLabelWidth, imageViewWidth), height);
Here we first adjust the size of title label, because it can be any size depending on the title set for the button. Then we get the width of both image view and the title label adding margins to them from both sides. Again, we calculate the height of the button, adding margins from both top and bottom.
margin
is a constant too, defined in the class and its value is6.0
We return a CGSize
created with the width of either image view or title label, which of them is greater, and the calculated height.
-intrinsicContentSize
provides a size value to be used in Interface Builder, so that whenever ‘Size to Fit Content’ is selected from the ‘Editor’ menu, it adjusts the button’s size according to this value.
Radius
We also have a public property named imageViewRadius
. This is used to round the corners of the image view. By default corner radius is set to be half of the image view’s width, so that it will be a perfect circle.
IB_DESIGNABLE & IBInspectable
These are the new keywords Xcode 6 introduced. Thanks to these we can see a preview of our custom coded view in Interface Builder!
IB_DESIGNABLE
tells Interface Builder that this is a custom view and needs a preview. We add this keyword just before class declaration in our header file.
IBInspectable
tells Interface Builder that the property with this keyword can be adjusted from the Attributes Inspector. We add this keyword just before the type of our property.
Result
Here is a screen shot of the example project:

I used this button as a profile button in my current project and wanted to open it to the world! So that, other developers in need of a control like this can benefit.
Feel free to contribute and let me know what you think in the comments!