For iOS7, I used the UIButton
titleLabel.frame.size.width
property to determine the width of my button title under different localisations so I could p
So we can try this code :
func withTitleAndImageAlign(title:String,image:UIImage,RL_Space:CGFloat) {
setNeedsLayout()
layoutIfNeeded()
let buttonWidth = frame.size.width
let textWidth = titleLabel?.frame.size.width
let imageWidth = imageView?.frame.size.width
let lim = buttonWidth - (textWidth! + imageWidth! + (2 * RL_Space) )
imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: lim)
titleEdgeInsets = UIEdgeInsets(top: 0, left: lim, bottom: 0, right: 0)
}
If you are then setting an image next to a button after getting the frame, you can use
[theButton setTitle: @"theTitle" forState:UIControlStateNormal];
[theButton setImage: theImage forState:UIControlStateNormal];
[theButton setNeedsLayout];
[theButton layoutIfNeeded];
[theButton setImageEdgeInsets: UIEdgeInsetsMake(6, transactionsButton.titleLabel.frame.size.width + 40.0, 0, 0)];
And in Swift 3, this will do.
self.view.layoutIfNeeded()
Maybe this will not work for you, but I had the same problem when running my code in XCode 6 GM / iOS8 and could not get it to work. It worked randomly and I ended up using a different approach instead of an NSString I used an NSAttributedString as the title.
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:@"Button text"];
NSTextAttachment* textAttachment = [NSTextAttachment new];
textAttachment.image = [UIImage imageNamed:@"Arrows"];
NSAttributedString *finalString = [NSAttributedString attributedStringWithAttachment:textAttachment];
[attributedText appendAttributedString:finalString];
Only caveat is that it’s iOS7 and up, but seems to work flawless.
Turns out I had greatly over engineered myself into this problem. I took out all of my content inset code and therefore didn't need to find the frame.size. I now just centre the button titles and all is well!
Still seems there is an issue with getting the frame.size but for my needs, I can work around it.
I resolved it. App run on iOS8, build by Xcode 6, not update frame right after UIButton setTitle
, setTitleEdgeInsets
. It will wait for next UI update. So, if you get frame of titleLabel, you will get CGRectZero.
Solution:
Call below methods after set UI property, to update layout immediately:
[self setNeedsLayout];
[self layoutIfNeeded];
Or:
titleFrame
, use self.titleLabel.frame
.Or:
Set the title text, then make a sizeToFit for the title label, and try to get the titleLabel.frame.size.width
[myButton setTitle:@"My Title" forState:UIControlStateNormal];
[myButton.titleLabel sizeToFit];