Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPhone UIButton - image position

People also ask

How do I use imageEdgeInsets?

The rule when it comes to titleEdgeInsets or imageEdgeInsets is to add equal and opposite offsets to the left and right insets. So if you add for example 8 points to the left title inset, you need to apply -8 points to the right inset.


My solution to this is quite simple

[button sizeToFit];
button.titleEdgeInsets = UIEdgeInsetsMake(0, -button.imageView.frame.size.width, 0, button.imageView.frame.size.width);
button.imageEdgeInsets = UIEdgeInsetsMake(0, button.titleLabel.frame.size.width, 0, -button.titleLabel.frame.size.width);

On iOS 9 onwards, seems that a simple way to achieve this is to force the semantic of the view.

enter image description here

Or programmatically, using:

button.semanticContentAttribute = .ForceRightToLeft

Set the imageEdgeInset and titleEdgeInset to move the components around within your image. You could also create a button using those graphics that is full size, and use that as the background image for the button (then use titleEdgeInsets to move the title around).


Raymond W's answer is best here. Subclass UIButton with custom layoutSubviews. Extremely simple to do, here's a layoutSubviews implementation that worked for me:

- (void)layoutSubviews
{
    // Allow default layout, then adjust image and label positions
    [super layoutSubviews];

    UIImageView *imageView = [self imageView];
    UILabel *label = [self titleLabel];

    CGRect imageFrame = imageView.frame;
    CGRect labelFrame = label.frame;

    labelFrame.origin.x = imageFrame.origin.x;
    imageFrame.origin.x = labelFrame.origin.x + CGRectGetWidth(labelFrame);

    imageView.frame = imageFrame;
    label.frame = labelFrame;
}

What about subclassing UIButton and overriding layoutSubviews?

Then post-processing the locations of self.imageView & self.titleLabel


Another simple way (that is NOT iOS 9 only) is to subclass UIButton to override these two methods

override func titleRectForContentRect(contentRect: CGRect) -> CGRect {
    var rect = super.titleRectForContentRect(contentRect)
    rect.origin.x = 0
    return rect
}

override func imageRectForContentRect(contentRect: CGRect) -> CGRect {
    var rect = super.imageRectForContentRect(contentRect)
    rect.origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(rect)
    return rect
}

contentEdgeInsets is already taken into account by using super.