UIButton titleLabel frame size returning CGSize wi

2020-05-19 07:18发布

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 position the title correctly using contentInset on the UIButton.

My UIButton is setup with an image and title and I always want the combination of these two to be centred horizontally in the UIButton for example:

[space-x (image) space-y (titleLabel) space-x]

Under iOS 7 and Xcode 5.1, the following code works perfectly (even running on iOS 8 GM when built in XCode 5.1):

CGSize buttonSize = button.frame.size;
CGSize titleSize = button.titleLabel.frame.size;
float contentInset =((buttonSize.width - (titleSize.width + 18 + 3)) / 2 );
float contentInsetRounded = roundf(contentInset);
[button setContentEdgeInsets:(UIEdgeInsetsMake(0, contentInsetRounded, 0, 0))];

(18 is the width of the image, and 3 is the number of points spacing between the image and titleLabel or space-y in my example above)

Under iOS 8 and Xcode 6 GM, button.titleLabel.frame.size is returning a CGSize with zero width & height so my contentInset ends up centring the UIImage in the UIButton, causing the titleLabel to truncate.

Any ideas? I tried setting the titleLabel text immediately before this code in case it thought it was empty but that didn't help either.

Thanks in advance!

标签: ios ios8
6条回答
仙女界的扛把子
2楼-- · 2020-05-19 07:27

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)
    }
查看更多
Evening l夕情丶
3楼-- · 2020-05-19 07:32

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()
查看更多
时光不老,我们不散
4楼-- · 2020-05-19 07:34

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.

查看更多
聊天终结者
5楼-- · 2020-05-19 07:36

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.

查看更多
看我几分像从前
6楼-- · 2020-05-19 07:37

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:

  1. Call below methods after set UI property, to update layout immediately:

    [self setNeedsLayout];
    [self layoutIfNeeded];

Or:

  1. Delay a second, and you can get titleFrame, use self.titleLabel.frame.

Or:

  1. dispatch_async in main queue, to move code to next queue
查看更多
霸刀☆藐视天下
7楼-- · 2020-05-19 07:43

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];
查看更多
登录 后发表回答