How to stop unwanted UIButton animation on title change? - objective-c

In iOS 7 my UIButton titles are animating in and out at the wrong time - late. This problem does not appear on iOS 6. I'm just using:
[self setTitle:text forState:UIControlStateNormal];
I would prefer this happens instantly and without a blank frame. This blink is especially distracting and draws attention away from other animations.

Use the performWithoutAnimation: method and then force layout to happen immediately instead of later on.
[UIView performWithoutAnimation:^{
[self.myButton setTitle:text forState:UIControlStateNormal];
[self.myButton layoutIfNeeded];
}];

This works for custom buttons:
[UIView setAnimationsEnabled:NO];
[_button setTitle:#"title" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];
For system buttons you need to add this before re-enabling animations (thank you #Klaas):
[_button layoutIfNeeded];

In Swift you can use :
UIView.performWithoutAnimation {
self.someButtonButton.setTitle(newTitle, forState: .normal)
self.someButtonButton.layoutIfNeeded()
}

Change button type to custom form interface builder.
This worked for me.

Please note :
when "buttonType" of _button is "UIButtonTypeSystem", below code is invalid:
[UIView setAnimationsEnabled:NO];
[_button setTitle:#"title" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];
when "buttonType" of _button is "UIButtonTypeCustom", above code is valid.

Starting in iOS 7.1 the only solution that worked for me was initializing the button with type UIButtonTypeCustom.

Swift 5
myButton.titleLabel?.text = "title"
myButton.setTitle("title", for: .normal)

so i find worked solution:
_logoutButton.titleLabel.text = NSLocalizedString(#"Logout",);
[_logoutButton setTitle:_logoutButton.titleLabel.text forState:UIControlStateNormal];
in first we change title for button, then resize button for this title

UIButton with system type has implicit animation on setTitle(_:for:). You can fix it two different ways:
Set the button type to custom, either from code or Interface Builder:
let button = UIButton(type: .custom)
Disable animation from code:
UIView.performWithoutAnimation {
button.setTitle(title, for: .normal)
button.layoutIfNeeded()
}

Set the button type to UIButtonTypeCustom and it'll stop flashing

I’ve made a Swift extension to do this:
extension UIButton {
func setTitleWithoutAnimation(title: String?) {
UIView.setAnimationsEnabled(false)
setTitle(title, forState: .Normal)
layoutIfNeeded()
UIView.setAnimationsEnabled(true)
}
}
Works for me on iOS 8 and 9, with UIButtonTypeSystem.
(The code is for Swift 2, Swift 3 and Objective-C should be similar)

Set UIButton type as Custom. That should remove fade in and out animations.

Usually simply setting the button type to Custom works for me, but for other reasons I needed to subclass UIButton and set the button type back to the default (System), so the blinking reappeared.
Setting UIView.setAnimationsEnabled(false) before changing the title and then to true again after that didn't avoid the blinking for me, no matter if I called self.layoutIfNeeded() or not.
This, and only this in the following exact order, worked for me with iOS 9 and 10 beta:
1) Create a subclass for UIButton (don't forget to set the custom class for the button in the Storyboard too).
2) Override setTitle:forState: as follows:
override func setTitle(title: String?, forState state: UIControlState) {
UIView.performWithoutAnimation({
super.setTitle(title, forState: state)
self.layoutIfNeeded()
})
}
In Interface Builder, you can leave the button type to System, no need to change it to Custom Type for this approach to work.
I hope this helps someone else, I've struggled for so long with the annoying blinking buttons that I hope to avoid it to others ;)

You can simply create Custom button and it will stop animate while changing the title.
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitle:#"the title" forState:UIControlStateNormal];
you also can do it in Storyboard checkbox:
select the button in storyboard -> select the attributes inspector (fourth from left side) -> in the 'Type' drop down menu, select 'Custom' instead of 'System' that was probably selected.
Good luck!

Swift 4 version of Xhacker Liu answer
import Foundation
import UIKit
extension UIButton {
func setTitleWithOutAnimation(title: String?) {
UIView.setAnimationsEnabled(false)
setTitle(title, for: .normal)
layoutIfNeeded()
UIView.setAnimationsEnabled(true)
}
}

You can remove the animations from from the title label's layer:
[[[theButton titleLabel] layer] removeAllAnimations];

You can actually set the title outside of an animation block, just be sure to call layoutIfNeeded() inside a performWithoutAnimation:
button1.setTitle("abc", forState: .Normal)
button2.setTitle("abc", forState: .Normal)
button3.setTitle("abc", forState: .Normal)
UIView.performWithoutAnimation {
self.button1.layoutIfNeeded()
self.button2.layoutIfNeeded()
self.button3.layoutIfNeeded()
}
If you have a bunch of buttons, consider just calling layoutIfNeeded() on the super view:
button1.setTitle("abc", forState: .Normal)
button2.setTitle("abc", forState: .Normal)
button3.setTitle("abc", forState: .Normal)
UIView.performWithoutAnimation {
self.view.layoutIfNeeded()
}

I've found that this workaround works with UIButtonTypeSystem as well but will only work if the button is enabled for some reason.
[UIView setAnimationsEnabled:NO];
[_button setTitle:#"title" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];
So you'll have to add these if you need the button to be disabled when setting its title.
[UIView setAnimationsEnabled:NO];
_button.enabled = YES;
[_button setTitle:#"title" forState:UIControlStateNormal];
_button.enabled = NO;
[UIView setAnimationsEnabled:YES];
(iOS 7, Xcode 5)

Combining above great answers results in following workaround for UIButtonTypeSystem:
if (_button.enabled)
{
[UIView setAnimationsEnabled:NO];
[_button setTitle:#"title" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];
}
else // disabled
{
[UIView setAnimationsEnabled:NO];
_button.enabled = YES;
[_button setTitle:#"title" forState:UIControlStateNormal];
_button.enabled = NO;
[UIView setAnimationsEnabled:YES];
}

I got the ugly animation problem when changing button titles in view controllers within a UITabBarController.
The titles that were originally set in the storyboard showed up for a short while before fading into their new values.
I wanted to iterate through all subviews and use the button titles as keys to get their localized values with NSLocalizedString, such as;
for(UIView *v in view.subviews) {
if ([v isKindOfClass:[UIButton class]]) {
UIButton *btn = (UIButton*)v;
NSString *newTitle = NSLocalizedString(btn.titleLabel.text, nil);
[btn setTitle:newTitle];
}
}
I found out that what's triggering the animation is really the call to btn.titleLabel.text.
So to still make use of the storyboards and have the components dynamically localized like this I make sure to set every button's Restoration ID (in Identity Inspector) to the same as the title and use that as key instead of the title;
for(UIView *v in view.subviews) {
if ([v isKindOfClass:[UIButton class]]) {
UIButton *btn = (UIButton*)v;
NSString *newTitle = NSLocalizedString(btn.restorationIdentifier, nil);
[btn setTitle:newTitle];
}
}
Not ideal, but works..

The Xhacker Liu extension converted to Swift 3 :
extension UIButton {
func setTitleWithoutAnimation(title: String?) {
UIView.setAnimationsEnabled(false)
setTitle(title, for: .normal)
layoutIfNeeded()
UIView.setAnimationsEnabled(true)
}
}

A convenient extension for animated button title change in Swift that plays nicely with the default implementation:
import UIKit
extension UIButton {
/// By default iOS animated the title change, which is not desirable in reusable views
func setTitle(_ title: String?, for controlState: UIControlState, animated: Bool = true) {
if animated {
setTitle(title, for: controlState)
} else {
UIView.setAnimationsEnabled(false)
setTitle(title, for: controlState)
layoutIfNeeded()
UIView.setAnimationsEnabled(true)
}
}
}

I got it to work with a combination of answers:
[[[button titleLabel] layer] removeAllAnimations];
[UIView performWithoutAnimation:^{
[button setTitle:#"Title" forState:UIControlStateNormal];
}];

Maybe generating 2 animations and 2 buttons is a better solution, to avoid the problem that is appearing with animating and changing the text of a button?
I created a second uibutton and generated 2 animation, this solution works with no hickups.
_button2.hidden = TRUE;
_button1.hidden = FALSE;
CGPoint startLocation = CGPointMake(_button1.center.x, button1.center.y - 70);
CGPoint stopLocation = CGPointMake(_button2.center.x, button2.center.y- 70);
[UIView animateWithDuration:0.3 animations:^{ _button2.center = stopLocation;} completion:^(BOOL finished){_button2.center = stopLocation;}];
[UIView animateWithDuration:0.3 animations:^{ _button1.center = startLocation;} completion:^(BOOL finished){_button1.center = startLocation;}];

Related

tvOS: Setting focus order

I currently have 3 objects called MenuButton that's a child of UIButton. These are defined in a row as shown in the image.
I've defined the highlight states in my MenuButton -didUpdateFocusInContext:withAnimationCoordinator method:
- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context
withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
{
if (context.nextFocusedView == self)
{
[self setTitleColor:[UIColor whiteColor]
forState:UIControlStateNormal];
}
else if (context.previouslyFocusedView == self)
{
[self setTitleColor:[UIColor colorWithRed:25.0/255.0
green:23.0/255.0
blue:16.0/255.0
alpha:1.0]
forState:UIControlStateNormal];
}
}
I've also set canBecomeFocused in the MenuButton object via:
- (BOOL)canBecomeFocused
{
return YES;
}
I've set my initial focus button using:
[_camerasButton setNeedsFocusUpdate]
When I swipe right on the Simulator remote, I'm not able to get it to focus on Deliveries.
Can someone please explain how I can use UIFocusGuide to implement this correctly in Objective-C?
UPDATE 1
Based on JustinVoss' suggestion on the first comment, I set breakpoint and did a _whyIsThisViewNotFocusable on the debug console. Received this hint:
(lldb) po [(UIView*)0x7ff68054f7c0 _whyIsThisViewNotFocusable]
ISSUE: This view may not be focusable because other views or focus guides are occluding it.
I'm defining my MenuButton frames as shown:
MenuButton *deliveriesButton = [MenuButton buttonWithType:UIButtonTypeCustom];
[deliveriesButton setTitle:#"Deliveries" forState:UIControlStateNormal];
[deliveriesButton setTitleColor:[UIColor colorWithRed:25.0/255.0
green:23.0/255.0
blue:16.0/255.0
alpha:1.0]
forState:UIControlStateNormal];
[deliveriesButton.titleLabel setFont:[Constants lightFontOfSize:39]];
[deliveriesButton sizeToFit];
deliveriesButton.center = CGPointMake(viewWidth/2,
menuBarHeight / 2);
[self.view addSubview:deliveriesButton];
_deliveriesButton = deliveriesButton;
Using the solution referenced by Justin Voss in the comments above, I went through the UIViews in my UIViewController and set:
view.userInteractionEnabled = NO;
on any view that I did not need to have a selection on (including background UIImageView objects). This resolved the problem.
Hope this helps someone else

AVPlayerViewController with custom overlay

Migrating to AVkit from MPMoviePlayer has brought me to a blocking issue.
I need to display a custom tableView over the AVPlayerViewController.
I can this tableview trough
[self.avVideoPlayer.contentOverlayView addsubiew:self.mycustomTableView]
and it is visible but it doesn't receive any tap/swipe events.
Any ideas why this happens or how can I add the table view in a place where it would receive the touch events even in the fullscreen mode?
[self.view addSubview:btn];
This will add the button in the minimised player.
Now for the fullscreen scenario you need to add an observer for the videoBounds, here is my code:
[self.avVideoPlayer addObserver:self forKeyPath:#"videoBounds" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
Now here comes the not so pretty part:
- (void)observeValueForKeyPath: (NSString*) path
ofObject: (id)object
change: (NSDictionary*)change
context: (void*)context {
NSLog(#"SOME OBSERVER DID THIS: %# , %#",object,change);
if ([self playerIsFullscreen]) {
for(UIWindow* tempWindow in [[UIApplication sharedApplication]windows]){
for(UIView* tempView in [tempWindow subviews]){
if ([[tempView description] rangeOfString:#"UIInputSetContainerView"].location != NSNotFound){
UIButton *testB = [[UIButton alloc] initWithFrame: CGRectMake(20, 20, 400, 400)];
testB.backgroundColor = [UIColor redColor];
[testB addTarget:self action:#selector(buttonTouch) forControlEvents:UIControlEventTouchDown];
[tempView addSubview:testB];
break;
}
}
}
}
}
I know this is a not a nice way to do it, but it is the only way I managed to add some custom UI that also receives touch events on the player.
Cheers!

Simple UIView animation move doesn't work

I have no idea, why it is not working.
All I want to do is a simple UIView animation in the viewDidLoad.
Here's my code:
[UIView animateWithDuration:3.0f animations:^{
[self.headline setCenter:CGPointMake(0.0, 200.0)];
}];
Nothing happens. When I test the general approach of calling a animation method on that particular object like this:
[UIView animateWithDuration:3.0f animations:^{
[self.headline setAlpha:0.0];
}];
it works!!! Why am I not able to move the view across the screen? I am using latest Xcode 4.5.
Thanks for any advice!
UPDATE:
When I add a view manually in code it works. But for the UIViews I create as Outlets in the Interface Builder it doesn't work.
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 200.0, 100.0)];
testLabel.backgroundColor = [UIColor redColor];
[self.view addSubview:testLabel];
[UIView animateWithDuration:3.0 animations:^{
testLabel.center = CGPointMake(0.0, 200);
}];
So obviously I am doing something wrong in the .xib file
Dont do it in viewDidLoad. The view is not pressent at that time yet.
Try it in viewDidAppear.
Well, I think the reason for the missing animation was the fact that I called a different push navigation animation from the view controller that was pushing the actual view on screen:
- (IBAction)goForSelection:(id)sender
{
SelectionViewController *selectionViewController = [[SelectionViewController alloc] initWithNibName:#"SelectionViewController" bundle:nil];
//[self.navigationController pushViewController:selectionViewController animated:YES];
[UIView transitionWithView:self.navigationController.view duration:1.0 options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
[self.navigationController pushViewController:selectionViewController animated:NO];
} completion:^(BOOL finished) {
[selectionViewController startIntroAnimation];
}];
}
First I checked what happens when I use the default navigation controller segue. And to my surprise the animation did start. Then I inserted the call to the [selectionViewController startIntroAnimation] to the completion block and this works as well.

How do I stop a UIButton's imageView from changing when pressed?

I have a method which sets a storyboard-placed UIButton's imageView property. After its set, it looks fine. However, when the button is tapped, its highlight state changes imageView's image property back to the old image. How do I stop this from happening? Here is my method:
- (void)setThumbButtonPhoto:(UIImage *)image
{
// profilePhoto is an IBOutlet property of class UIButton pointing to the
// UIButton on my storyboard.
// Button image is changed correctly here
profilePhoto.imageView.image = image;
// But then mysteriously changed back to the old image when tapped.
// The following commented out lines I have all tried (one at a time of course)
// and none have solved my problem -->
// [profilePhoto.imageView setHighlightedImage:nil];
// profilePhoto.imageView.highlightedImage = image;
// profilePhoto.adjustsImageWhenHighlighted = NO;
// [profilePhoto setBackgroundImage:image forState:UIControlStateHighlighted];
// [profilePhoto setImage:image forState:UIControlStateNormal];
// [profilePhoto setImage:image forState:UIControlStateHighlighted];
// [profilePhoto setImage:image forState:UIControlStateSelected];
}
You should use this method to set the image properly on your button:
- (void)setImage:(UIImage *)image forState:(UIControlState)state
So:
[profilePhoto setImage:image forState:UIControlStateNormal];
[profilePhoto setImage:image forState:UIControlStateHighlighted];
use an UIImageView to hold the image
and put a Custom mode UIButton, no text, no image, no background ; under it

Is it possible to change a UIButtons background color?

This one has me stumped.
Is it possible at all to change the background color of a UIButton in Cocoa for iPhone.
I've tried setting the background color but it only changes the corners. setBackgroundColor: seems to be the only method available for such things.
[random setBackgroundColor:[UIColor blueColor]];
[random.titleLabel setBackgroundColor:[UIColor blueColor]];
This can be done programmatically by making a replica:
loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
[loginButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
loginButton.backgroundColor = [UIColor whiteColor];
loginButton.layer.borderColor = [UIColor blackColor].CGColor;
loginButton.layer.borderWidth = 0.5f;
loginButton.layer.cornerRadius = 10.0f;
edit: of course, you'd have to #import <QuartzCore/QuartzCore.h>
edit: to all new readers, you should also consider a few options added as "another possibility". for you consideration.
As this is an old answer, I strongly recommend reading comments for troubleshooting
I have a different approach,
[btFind setTitle:NSLocalizedString(#"Find", #"") forState:UIControlStateNormal];
[btFind setBackgroundImage:[CommonUIUtility imageFromColor:[UIColor cyanColor]]
forState:UIControlStateNormal];
btFind.layer.cornerRadius = 8.0;
btFind.layer.masksToBounds = YES;
btFind.layer.borderColor = [UIColor lightGrayColor].CGColor;
btFind.layer.borderWidth = 1;
From CommonUIUtility,
+ (UIImage *) imageFromColor:(UIColor *)color {
CGRect rect = CGRectMake(0, 0, 1, 1);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
// [[UIColor colorWithRed:222./255 green:227./255 blue: 229./255 alpha:1] CGColor]) ;
CGContextFillRect(context, rect);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Don't forget to #import <QuartzCore/QuartzCore.h>
I assume you're talking about a UIButton with UIButtonTypeRoundedRect?
You can't change the background color of that. When you try changing it's background color you're rather changing the color of the rect the button is drawn on (which is usually clear).
So there are two ways to go. Either you subclass UIButton and overwrite its -drawRect: method or you create images for the different button states (which is perfectly fine to do).
If you set the background images in Interface Builder you should notice that IB doesn't support setting images for all the states the button can have, so I recommend setting the images in code like this:
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setBackgroundImage:[UIImage imageNamed:#"normal.png"] forState:UIControlStateNormal];
[myButton setBackgroundImage:[UIImage imageNamed:#"disabled.png"] forState:UIControlStateDisabled];
[myButton setBackgroundImage:[UIImage imageNamed:#"selected.png"] forState:UIControlStateSelected];
[myButton setBackgroundImage:[UIImage imageNamed:#"higligted.png"] forState:UIControlStateHighlighted];
[myButton setBackgroundImage:[UIImage imageNamed:#"highlighted+selected.png"] forState:(UIControlStateHighlighted | UIControlStateSelected)];
The last line shows how to set an image for the selected & highlighted state (that's the one IB can't set).
You don't need the selected images (line 4 & 6) if you're button dosn't need a selected state.
Another possibility:
Create a UIButton in Interface builder.
Give it a type 'Custom'
Now, in IB it is possible to change the background color
However, the button is square, and that is not what we want. Create an IBOutlet with a reference to this button and add the following to the viewDidLoad method:
[buttonOutlet.layer setCornerRadius:7.0f];
[buttonOutlet.layer setClipToBounds:YES];
Don't forget to import QuartzCore.h
Subclass UIButton and override setHighlighted and setSelected methods
-(void) setHighlighted:(BOOL)highlighted {
if(highlighted) {
self.backgroundColor = [self.mainColor darkerShade];
} else {
self.backgroundColor = self.mainColor;
}
[super setHighlighted:highlighted];
}
-(void) setSelected:(BOOL)selected {
if(selected) {
self.backgroundColor = [self.mainColor darkerShade];
} else {
self.backgroundColor = self.mainColor;
}
[super setSelected:selected];
}
My darkerShade method is in a UIColor category like this
-(UIColor*) darkerShade {
float red, green, blue, alpha;
[self getRed:&red green:&green blue:&blue alpha:&alpha];
double multiplier = 0.8f;
return [UIColor colorWithRed:red * multiplier green:green * multiplier blue:blue*multiplier alpha:alpha];
}
If you are not wanting to use images, and want it to look exactly like the Rounded Rect style, try this. Just place a UIView over the UIButton, with an identical frame and auto resize mask, set the alpha to 0.3, and set the background to a color. Then use the snippet below to clip the rounded edges off the colored overlay view. Also, uncheck the 'User Interaction Enabled' checkbox in IB on the UIView to allow touch events to cascade down to the UIButton underneath.
One side effect is that your text will also be colorized.
#import <QuartzCore/QuartzCore.h>
colorizeOverlayView.layer.cornerRadius = 10.0f;
colorizeOverlayView.layer.masksToBounds = YES;
Another possibility (the best and most beautiful imho):
Create a UISegmentedControl with 2 segments in the required background color in Interface Builder. Set the type to 'bar'. Then, change it to having only one segment. Interface builder does not accept one segment so you have to do that programmatically.
Therefore, create an IBOutlet for this button and add this to the viewDidLoad of your view:
[segmentedButton removeSegmentAtIndex:1 animated:NO];
Now you have a beautiful glossy, colored button with the specified background color.
For actions, use the 'value changed' event.
(I have found this on http://chris-software.com/index.php/2009/05/13/creating-a-nice-glass-buttons/). Thanks Chris!
Well I'm 99% percent positive that you cannot just go and change the background color of a UIButton. Instead you have to go and change the background images yourself which I think is a pain. I'm amazed that I had to do this.
If I'm wrong or if theres a better way without having to set background images please let me know
[random setBackgroundImage:[UIImage imageNamed:#"toggleoff.png"] forState:UIControlStateNormal];
[random setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal];
[random setBackgroundImage:[UIImage imageNamed:#"toggleon.png"] forState:UIControlStateNormal];
[random setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
Per #EthanB suggestion and #karim making a back filled rectangle, I just created a category for the UIButton to achieve this.
Just drop in the Category code: https://github.com/zmonteca/UIButton-PLColor
Usage:
[button setBackgroundColor:uiTextColor forState:UIControlStateDisabled];
Optional forStates to use:
UIControlStateNormal
UIControlStateHighlighted
UIControlStateDisabled
UIControlStateSelected
You can also add a CALayer to the button - you can do lots of things with these including a color overlay, this example uses a plain color layer you can also easily graduate the colour. Be aware though added layers obscure those underneath
+(void)makeButtonColored:(UIButton*)button color1:(UIColor*) color
{
CALayer *layer = button.layer;
layer.cornerRadius = 8.0f;
layer.masksToBounds = YES;
layer.borderWidth = 4.0f;
layer.opacity = .3;//
layer.borderColor = [UIColor colorWithWhite:0.4f alpha:0.2f].CGColor;
CAGradientLayer *colorLayer = [CAGradientLayer layer];
colorLayer.cornerRadius = 8.0f;
colorLayer.frame = button.layer.bounds;
//set gradient colors
colorLayer.colors = [NSArray arrayWithObjects:
(id) color.CGColor,
(id) color.CGColor,
nil];
//set gradient locations
colorLayer.locations = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0f],
[NSNumber numberWithFloat:1.0f],
nil];
[button.layer addSublayer:colorLayer];
}
add a second target for the UIButton for UIControlEventTouched and change the UIButton background color. Then change it back in the UIControlEventTouchUpInside target;
For professional and nice looking buttons, you may check this custom button component. You can use it directly in your views and tableviews or modify the source code to make it meet your needs. Hope this helps.
This isn't as elegant as sub-classing UIButton, however if you just want something quick - what I did was create custom button, then a 1px by 1px image with the colour I'd want the button to be, and set the background of the button to that image for the highlighted state - works for my needs.
I know this was asked a long time ago and now there's a new UIButtonTypeSystem. But newer questions are being marked as duplicates of this question so here's my newer answer in the context of an iOS 7 system button, use the .tintColor property.
let button = UIButton(type: .System)
button.setTitle("My Button", forState: .Normal)
button.tintColor = .redColor()
[myButton setBackgroundColor:[UIColor blueColor]];
[myButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
It's possible change this way or going on Storyboard and change background on options in right side.
Swift 3:
static func imageFromColor(color: UIColor, width: CGFloat, height: CGFloat) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: width, height: height)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()!
context.setFillColor(color.cgColor)
context.fill(rect)
let img = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return img
}
let button = UIButton(type: .system)
let image = imageFromColor(color: .red, width:
button.frame.size.width, height: button.frame.size.height)
button.setBackgroundImage(image, for: .normal)
For iOS 15+ Apple provides a simple button configuration to accomplish this.
Objective-C:
randomButton.configuration = [UIButtonConfiguration filledButtonConfiguration];
Swift:
randomButton.configuration = .filled()