UIButton, as we all know, does not support setting image and text spacing.

Most articles on the Internet use titleEdgeInsets and imageEdgeInsets to separate images from text, but this method does not automatically change the size of the button, so the problem is that after adjusting the spacing, you need to calculate the size of the button. And there is no automatic resizing for AutoLayout.

To address these pain points, a better way to subclass UIButton is to add a spacing attribute to spacing. To set spacing, change spacing directly to spacing. Define spacing like this:

@interface ZUIButton : UIButton

@property(nonatomic) CGFloat spacing;

@end
Copy the code

Since increasing the spacing changes the size of the buttons, we also need to adjust the implementation of intrinsicContentSize and sizeToFit to be fully compatible with AutoLayout and frame based manual layouts:

- (CGSize)intrinsicContentSize {
    CGSize size = [super intrinsicContentSize];

    CGSize imageSize = self.currentImage.size;
    if ((self.currentTitle.length > 0 || self.currentAttributedTitle.length > 0) &&
        (imageSize.width > 0 && imageSize.height > 0)) {
        size.width += _spacing;
    }

    return size;
}
Copy the code
- (void)sizeToFit {
    [super sizeToFit];

    CGRect bounds = self.bounds;
    bounds.size = [self intrinsicContentSize];
    self.bounds = bounds;

    CGFloat offset = 0;
    CGSize imageSize = self.currentImage.size;
    if ((self.currentTitle.length > 0 || self.currentAttributedTitle.length > 0) &&
        (imageSize.width > 0 && imageSize.height > 0)) {
        offset = _spacing * 0.5;
    }

    CGPoint center = self.center;
    center.x += offset;
    self.center = center;
}
Copy the code

This makes it easy for subclassed ZUIButton spacing to be set using spacing.

A further extension: support for setting the position of images and text. By default, the button can only be the image left text right style, sometimes encounter the need for text left image right scene, can not meet.

Continue to extend ZUIButton to support text left image right display style.

The display area of images and text is determined by imageRectForContentRect and titleRectForContentRect. It’s easy to inherit these two methods and swap coordinates internally.

Add an enumeration type ZUIButtonDirection to set the display direction:

typedef NS_ENUM(NSInteger, ZUIButtonDirection) {
    ZUIButtonDirectionRow = 0.// Default style: image left, text right
    ZUIButtonDirectionRowReverse  // Text left, image right
};
Copy the code

Added a new property to set the display direction: direction

@interface ZUIButton : UIButton

@property(nonatomic) CGFloat spacing;

@property(nonatomic) ZUIButtonDirection direction;

@end
Copy the code

Reposition the image and text according to the direction setting:

- (CGRect)imageRectForContentRect:(CGRect)contentRect {
    CGRect rect = [super imageRectForContentRect:contentRect];

    if (_direction == ZUIButtonDirectionRowReverse) {
        CGRect titleRect = [super titleRectForContentRect:contentRect];
        titleRect.origin.x = rect.origin.x;
        rect.origin.x = CGRectGetMaxX(titleRect);
    }

    if (self.currentTitle.length > 0 || self.currentAttributedTitle.length > 0) {
        if (_direction == ZUIButtonDirectionRow) {
            rect.origin.x -= _spacing * 0.5;
        } else if (_direction == ZUIButtonDirectionRowReverse) {
            rect.origin.x += _spacing * 0.5; }}return rect;
}
Copy the code
- (CGRect)titleRectForContentRect:(CGRect)contentRect {
    CGRect rect = [super titleRectForContentRect:contentRect];

    if (_direction == ZUIButtonDirectionRowReverse) {
        CGRect imageRect = [super imageRectForContentRect:contentRect];
        rect.origin.x = imageRect.origin.x;
    }

    CGSize imageSize = self.currentImage.size;
    if (imageSize.width > 0 && imageSize.height > 0) {
        if (_direction == ZUIButtonDirectionRow) {
            rect.origin.x += _spacing * 0.5;
        } else if (_direction == ZUIButtonDirectionRowReverse) {
            rect.origin.x -= _spacing * 0.5; }}return rect;
}
Copy the code

Now, ZUIButton is easy to use.

Don’t want to change the UIButton in your existing project to ZUIButton? Let’s try the Method Swizzling implementation and make it a UIButton category:

Github.com/cntrump/UIB…