Introduction to UIEdgeInsetsMake

UIEdgeInsetsMake references: UIEdgeInsetsMake uses detailed images and explanations, plus its own understanding and implementation

Look at the definition

typedef struct UIEdgeInsets { 
  CGFloat top, left, bottom, right; // specify amount to inset (positive) for each of the edges. values can be negative to 'outset'
} UIEdgeInsets;
Copy the code

UIEdgeInsets are actually a structure:

UIEdgeInsetsMake(CGFloat top ,  CGFloat left ,  CGFloat bottom ,  CGFloat right )
Copy the code

Warning: Left is positive, right is positive, top is positive and bottom is positive

Let’s start with a picture:

In the figure, blue marks are variable areas and green marks are invariant areas. The top and bottom properties of the UIEdgeInsets structure are paired to specify vertical mutable areas (black dotted rectangles) and left and right are paired to specify horizontal mutable areas (white dotted rectangles). When the size of UIButton/UIImageView is larger than the size of UIImage, the variable area in the image will be adjusted to cover the entire control as follows:

  • (1) Control width is larger than the picture width, stretch the white dotted rectangle
  • (2) Control height is greater than the picture height, stretch the black dotted rectangle
  • (3) When the width of the control is smaller than the width of the picture, the horizontal overall reduction (the ratio of variable area and constant area remains unchanged)
  • (4) When the height of the control is smaller than the height of the picture, the overall longitudinal reduction (the ratio of variable area and invariant area remains unchanged)

Explanation: THESE four sentences summary I do not know you have understood, anyway I did not understand.

UIEdgeInsetsMake applied to UIButton

It’s full of quotes from other people. It’s time to talk about your own content.

UIEdgeInsetsMake(CGFloat top , CGFloat left , CGFloat bottom , CGFloat right )
Copy the code

UIEdgeInsetsMake is a structure that describes the inner margin of the content inside the wrapper container, so UIButton, for example, the Image inside a button is the content, button is the wrapper container, We can use UIEdgeInsetsMake to describe the inner margin of an Image inside a button. In the case of “UIEdgeInsets”, once UIEdgeInsetsMake is set, the position of the Image is the middle area where the black dotted line and the white dotted line overlap. One of the preconditions for this kind of understanding is to describe individual contents, like in UIButton where you just set Image or just set TitleLabel, when you set both Image and TitleLabel, there’s a little bit of a difference, but let’s talk about that.

Going back to UIEdgeInsetsMake use of UIEdgeInsetsMake of UIButton, I’m sure a lot of people have encountered that kind of requirement, which is the original button image on the left, title on the right, and a lot of times that’s true, But sometimes the requirement may be “picture on top, title on bottom” or “picture on right, title on left”, as shown below:

So now we have to use UIEdgeInsetsMake to set our own buttons. It says content is a single and multiple is different, what’s the difference?

For a button with image and title set, the system automatically sets the appropriate ImageEdgeInsets and TitleEdgeInsets

Q: What do you mean appropriate? A: If you create a new button and display it, you will find that the margins are really appropriate. Although sometimes the title is not completely displayed together, at least the margins look good. So I don’t know what is appropriate, I only know that after setting image and title for a new button, There’s a default ImageEdgeInsets and TitleEdgeInsets.

After setting image and title, print the margins:

//生成button
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitle:"This is a button" forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:@"image"] forState:UIControlStateNormal];
button.frame = CGRectMake(100.100.160.40);
button.backgroundColor = [UIColor redColor];
button.titleLabel.backgroundColor = [UIColor purpleColor];
[self.view addSubview:button];

/ / print before
NSLog(@"before-->%@".NSStringFromUIEdgeInsets(button.imageEdgeInsets));
NSLog(@"before-->%@".NSStringFromUIEdgeInsets(button.titleEdgeInsets));

// Modify the margins
button.imageEdgeInsets = UIEdgeInsetsMake(0, button.titleLabel.intrinsicContentSize.width, 0, -button.titleLabel.intrinsicContentSize.width);
button.titleEdgeInsets = UIEdgeInsetsMake(0, -button.currentImage.size.width, 0, button.currentImage.size.width);

/ / after printing
NSLog(@"after-->%@".NSStringFromUIEdgeInsets(button.imageEdgeInsets));
NSLog(@"after-->%@".NSStringFromUIEdgeInsets(button.titleEdgeInsets));
Copy the code

You see the margins, you see they both print out as (0,0,0,0) and (0,0,0,0).

WTF??? This is obviously not zero, so I’m guessing that this is not actually the margin of the image and titleLabel relative to the button, but an offset from the base margin.

After setting the image and title of the button, the system automatically sets the ImageEdgeInsets and TitleEdgeInsets that fit properly. So we’re printing before and we’re probably not printing the actual imageEdgeInsets and titleEdgeInsets, we’re printing the EdgeInsets that we set, because we didn’t set them, so we’re printing (0,0,0,0), and then when we set them, {0, 110.5, 0, -110.5} and {0, -23, 0, 23} were printed. Here are two lines of code to set:

button.imageEdgeInsets = UIEdgeInsetsMake(0, button.titleLabel.intrinsicContentSize.width, 0, -button.titleLabel.intrinsicContentSize.width);
button.titleEdgeInsets = UIEdgeInsetsMake(0, -button.currentImage.size.width, 0, button.currentImage.size.width);
Copy the code

One to update the image margin and one to update the title margin. We need to move the image right by the width of a titleLabel, so we need to move both the left and right margins of the image right by a titleLabel. Warning: the navigation left will be positive, and the navigation right will be positive. The navigation top will be positive, and the navigation bottom will be positive. You can see the navigation constraint set for you.

We use the button. The titleLabel. IntrinsicContentSize. Width calculating the width of the titleLabel (tips: Use the button. The titleLabel. Bounds. Size. The width of the above iOS8 will get the result of the width of 0, the wrong result), and then because the image will shift to the right of left and right, the width of a titleLabel and left to right as the positive direction, Right is the right direction. So is to set up the UIEdgeInsetsMake (0, button. The titleLabel. IntrinsicContentSize. Width, 0, -button.titleLabel.intrinsicContentSize.width); Similarly, titleLabel needs to be moved one image width to the left, in the direction we expect: button.titleEdgeInsets = UIEdgeInsetsMake(0, -button.currentImage.size.width, 0, button.currentImage.size.width); Here need to pay attention to use the button. The currentImage. Size. The effect is better than the calculated width button. The imageView calculated width

3. Summary Mode:

  • Picture on the left, title on the right
  • Picture on top, title on bottom
  • Picture on the right, title on the left
  • Picture on the bottom, title on the top

Post the code and I won’t go through it:

- (void)layoutButtonWithEdgeInsetsStyle:(MKButtonEdgeInsetsStyle)style
                        imageTitleSpace:(CGFloat)space {
    // 1. Get the width and height of imageView and titleLabel
    // CGFloat imageWith = self.imageView.frame.size.width;
    // CGFloat imageHeight = self.imageView.frame.size.height;
    CGFloat imageWith = self.currentImage.size.width;
    CGFloat imageHeight = self.currentImage.size.height;
    
    CGFloat labelWidth = 0.0;
    CGFloat labelHeight = 0.0;
    if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
        // Since titleLabel size in iOS8 is 0, use the following setting
        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;
    
    // select imageEdgeInsets and labelEdgeInsets based on style and space
    switch (style) {
        case MKButtonEdgeInsetsStyleTop: {
            imageEdgeInsets = UIEdgeInsetsMake(-labelHeight-space, 0.0, -labelWidth);
            labelEdgeInsets = UIEdgeInsetsMake(0, -imageWith, -imageHeight-space, 0);
        }
            break;
        case MKButtonEdgeInsetsStyleLeft: {
            imageEdgeInsets = UIEdgeInsetsMake(0, -space, 0, space);
            labelEdgeInsets = UIEdgeInsetsMake(0, space, 0, -space);
        }
            break;
        case MKButtonEdgeInsetsStyleBottom: {
            imageEdgeInsets = UIEdgeInsetsMake(0.0, -labelHeight-space, -labelWidth);
            labelEdgeInsets = UIEdgeInsetsMake(-imageHeight-space, -imageWith, 0.0);
        }
            break;
        case MKButtonEdgeInsetsStyleRight: {
            imageEdgeInsets = UIEdgeInsetsMake(0, labelWidth+space, 0, -labelWidth-space);
            labelEdgeInsets = UIEdgeInsetsMake(0, -imageWith-space, 0, imageWith+space);
        }
            break;
        default:
            break;
    }
    4 / / assignment
    self.titleEdgeInsets = labelEdgeInsets;
    self.imageEdgeInsets = imageEdgeInsets;
}

Copy the code

4. Contact information

Email: [email protected] Related Account:

  • Denver – Adrenine
  • Jane – Adrenine book
  • Blog – Adrenine
  • Github – Adrenine