今是昨非

今是昨非

日出江花红胜火,春来江水绿如蓝

Implement Button text (titleLabel) and image (imageView) arranged vertically.

Implementing Button Text (titleLabel) and Image (imageView) Arrangement in Vertical Order#

  1. Initially, I implemented this using the following method:
    Creating a custom view with two properties, label and imageView, and then setting their positions and layouts. Then, adding a tap gesture recognizer and using a delegate to pass back the click method.
  1. Second method:
    Creating a custom Button that inherits from Button, with two properties, label and imageView, and then setting the layout. This way, there is no need to add a tap gesture recognizer.
  1. Third method:
    Directly using the titleLabel and imageView provided by the Button, writing a Category to set the arrangement of the label and image, e.g. top-bottom, left-right.

Clearly, the first two methods are not good, so let's focus on the third method:

The Button has two properties: titleEdgeInsets and imageEdgeInsets. By setting these two, we can achieve all the required styles for the Button, such as image on top, image on bottom, image on left, and image on right.

Before setting these two, we need to understand the relationship between the titleLabel and imageView on the Button (imagine the default display of image and label on the Button):

  1. titleEdgeInsets is the inset of the titleLabel relative to its top, bottom, left, and right, similar to tableView's contentInset;
  2. If there is only a title, then the titleLabel's top, bottom, left, and right are all relative to the Button;
  3. If there is only an image, then the imageView's top, bottom, left, and right are all relative to the Button;
  4. If there is both an image and a label, then the image's top, bottom, and left are relative to the Button, and the right is relative to the label. The label's top, bottom, and right are relative to the Button, and the left is relative to the label.

The above paragraph is very important#

Once we understand this, we can understand the following code:

  1. Create a Category for Button, the .h file is as follows, defining an Enum to determine the style of the image and label, and a method to call the settings.

#import <UIKit/UIKit.h>
typedef NS_ENUM(NSUInteger, MKButtonEdgeInsetsStyle) {
    MKButtonEdgeInsetsStyleTop, // image on top, label on bottom
    MKButtonEdgeInsetsStyleLeft, // image on left, label on right
    MKButtonEdgeInsetsStyleBottom, // image on bottom, label on top
    MKButtonEdgeInsetsStyleRight // image on right, label on left
};
@interface UIButton (ImageTitleSpacing)
/**
 *  Set the layout style and spacing between the button's titleLabel and imageView
 *
 *  @param style The layout style of the titleLabel and imageView
 *  @param space The spacing between the titleLabel and imageView
 */
- (void)layoutButtonWithEdgeInsetsStyle:(MKButtonEdgeInsetsStyle)style
                    imageTitleSpace:(CGFloat)space;
  1. The .m file is as follows, implementing the method

#import "UIButton+ImageTitleSpacing.h"
@implementation UIButton (ImageTitleSpacing)
- (void)layoutButtonWithEdgeInsetsStyle:(MKButtonEdgeInsetsStyle)style
                    imageTitleSpace:(CGFloat)space
{
    // 1. Get the width and height of the imageView and titleLabel
    CGFloat imageWith = self.imageView.frame.size.width;
    CGFloat imageHeight = self.imageView.frame.size.height;
    
    CGFloat labelWidth = 0.0;
    CGFloat labelHeight = 0.0;
    if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
        // In iOS 8, the titleLabel's size is 0, so we use the following method
        labelWidth = self.titleLabel.intrinsicContentSize.width;
        labelHeight = self.titleLabel.intrinsicContentSize.height;
    } else {
        labelWidth = self.titleLabel.frame.size.width;
        labelHeight = self.titleLabel.frame.size.height;
    }
    
    // 2. Declare global imageEdgeInsets and labelEdgeInsets
    UIEdgeInsets imageEdgeInsets = UIEdgeInsetsZero;
    UIEdgeInsets labelEdgeInsets = UIEdgeInsetsZero;
    
    // 3. Get the values of imageEdgeInsets and labelEdgeInsets based on the style and space
    switch (style) {
        case MKButtonEdgeInsetsStyleTop:
        {
            imageEdgeInsets = UIEdgeInsetsMake(-labelHeight-space/2.0, 0, 0, -labelWidth);
            labelEdgeInsets = UIEdgeInsetsMake(0, -imageWith, -imageHeight-space/2.0, 0);
        }
            break;
        case MKButtonEdgeInsetsStyleLeft:
        {
            imageEdgeInsets = UIEdgeInsetsMake(0, -space/2.0, 0, space/2.0);
            labelEdgeInsets = UIEdgeInsetsMake(0, space/2.0, 0, -space/2.0);
        }
            break;
        case MKButtonEdgeInsetsStyleBottom:
        {
            imageEdgeInsets = UIEdgeInsetsMake(0, 0, -labelHeight-space/2.0, -labelWidth);
            labelEdgeInsets = UIEdgeInsetsMake(-imageHeight-space/2.0, -imageWith, 0, 0);
        }
            break;
        case MKButtonEdgeInsetsStyleRight:
        {
            imageEdgeInsets = UIEdgeInsetsMake(0, labelWidth+space/2.0, 0, -labelWidth-space/2.0);
            labelEdgeInsets = UIEdgeInsetsMake(0, -imageWith-space/2.0, 0, imageWith+space/2.0);
        }
            break;
        default:
            break;
    }
    // 4. Assign the values
    self.titleEdgeInsets = labelEdgeInsets;
    self.imageEdgeInsets = imageEdgeInsets;
}

I created a demo on GitHub, here is the link: Custom Button

References#

  1. UIButton's titleEdgeInsets and imageEdgeInsets properties to achieve the desired arrangement of images and text, this blog explains the above principles, I recommend reading it carefully to understand.
  2. UIButton's imageEdgeInsets and titleEdgeInsets, this blog has a GitHub link at the end, when I was writing, I didn't understand the principles, so when setting it, I referred to their code.
  3. How to layout a UIButton with both Image and Title, this was my initial reference, it only has the code, without the principles.
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.