IOS UIButton is a very common and commonly used control, we usually use it to achieve a function of submission and selection operations. We can create a Button with only text, or a Button with only pictures. The specific requirements depend on the specific situation of the interface design. Sometimes we want the interface elements of the application to be rich and colorful, and sometimes we want to build a combination of graphics and text control to respond to the user’s gesture operation, so we build a button with both pictures and text to achieve the function. UIButton setTitle:forState: and setImage:forSate: call UIButton setTitle:forState: and setImage:forSate: respectively to implement the image and text functions of the button. But the default combination of graphics and text button layout: image on the left and text on the right, and overall horizontal and vertical center. For example, the following graphic button:
UIImageView
UILabel
UIButton
UIImageView
UILabel
UIButton
UIButton
UIImageView
UILabel
UIButton
UIButton
UIButton
UIButton
UIImageView
UIButton
@property(nonatomic,readonly,retain)UILabel *titleLabel NS_AVAILABLE_IOS(3_0);
@property(nonatomic,readonly,retain)UIImageView *imageView NS_AVAILABLE_IOS(3_0);
Copy the code
It is important to note that two attributes must finish call setTitle: forSate: and setImage: forSate: to get to, or likely will return nil. The titleLabel is for text and the imageView is for images. Since UIButton itself has an image control and a text control, can we just adjust the frame value of the child control to achieve any layout we want for the image and text? The answer is no. It turns out that setting the titleLabel and imageView frame values doesn’t change the image to the left and the text to the right. To implement the functionality, you must use two additional attributes:
@property(nonatomic) UIEdgeInsets titleEdgeInsets; // default is UIEdgeInsetsZero
@property(nonatomic) UIEdgeInsets imageEdgeInsets; // default is UIEdgeInsetsZero
Copy the code
These two attributes are used to adjust the button text respectively the excursion of the indentation indentation and pictures, they are all a UIEdgeInsets object, the default value is 0, which is the default value is 0 button images and text under the condition of vertical center, and photos on the left on the right side, and the overall level of the image text center. We can adjust titleEdgeInsets and imageEdgeInsets to achieve any layout we want, even if we want some space between the image and the text. How to adjust? How much is the best adjustment?
Before adjusting, we define a few specific variable values:
: CGRect titleRect = titleLabel.frame; // The frame value of the text control in the button. CGRect imageRect = imageView.frame; // The frame value of the picture control in the button. CGFloat padding; // Used to specify spacing values for text and images. CGFloat selfWidth; // The width of the button control CGFloat selfHeight; CGFloat totalHeight= titlerect.size. Height +padding+imageRect.size. Height; // The total height of the text, including the padding between them
We can adjust the position of the text and image by changing the titleEdgeInsets and imageEdgeInsets of the button. If we want to move 20 to the right, then we should set the UIEdgeInsets left=20, right=-20, and if we want to move 20 up, we should set the UIEdgeInsets top=-20,bottom=20. TitleEdgeInsets and imageEdgeInsets are used to set the titleEdgeInsets and imageEdgeInsets.
First, the picture is on the left, the text is on the right, the whole center, adjust the spacing
padding/2
padding/2
titleEdgeInsets =UIEdgeInsetsMake(0,
padding/2,
0,
-padding/2);
imageEdgeInsets = UIEdgeInsetsMake(0,
-padding/2,
0,
padding/2);
Copy the code
2. Picture on the right, text on the left, overall center
padding/2
padding/2
titleEdgeInsets =UIEdgeInsetsMake(0,
-(imageRect.size.width + padding/2),
0,
(imageRect.size.width + padding/2));
imageEdgeInsets =UIEdgeInsetsMake(0,
(titleRect.size.width+ padding/2),
0,
-(titleRect.size.width+ padding/2));
Copy the code
## 3. Picture on top, text on bottom, overall center
imageRect.origin.y
selfWidth/2
imageRect.origin.x + imageRect.size.width/2
imageRect.size.height
padding
titleRect.origin.y
selfWidth/2
titleRect.origin.x + titleRect.size.width/2
By default, when the button is small, the size of the image will be kept and the text part will be reduced. When the text and picture are arranged up and down, the text area needs to be extended to the whole button part, otherwise the text width of the button will be reduced
selfWidth
titleRect.size.width
Consider this case whenever text and images are vertically centered in each of the styles below
titleEdgeInsets =UIEdgeInsetsMake(((selfHeight - totalHeight)/2 + imageRect.size.height + padding - titleRect.origin.y), (selfWidth/2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) /2, -((selfHeight - totalHeight)/2 + imageRect.size.height + padding - titleRect.origin.y), -(selfWidth/2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) /2); imageEdgeInsets =UIEdgeInsetsMake(((selfHeight - totalHeight)/2 - imageRect.origin.y), (selfWidth /2 - imageRect.origin.x - imageRect.size.width /2), -((selfHeight - totalHeight)/2 - imageRect.origin.y), -(selfWidth /2 - imageRect.origin.x - imageRect.size.width /2));Copy the code
## 4. The picture is at the bottom, the text is at the top, and the whole is in the center
titleEdgeInsets =UIEdgeInsetsMake(((selfHeight - totalHeight)/2 - titleRect.origin.y), (selfWidth/2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) /2, -((selfHeight - totalHeight)/2 - titleRect.origin.y), -(selfWidth/2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) /2); imageEdgeInsets =UIEdgeInsetsMake(((selfHeight - totalHeight)/2 + titleRect.size.height + padding - imageRect.origin.y), (selfWidth /2 - imageRect.origin.x - imageRect.size.width /2), -((selfHeight - totalHeight)/2 + titleRect.size.height + padding - imageRect.origin.y), -(selfWidth /2 - imageRect.origin.x - imageRect.size.width /2));Copy the code
5. The image should be centered, while the text should be centered and the top of the text should be away from the top of the button
padding
titleRect.origin.y
titleRect.origin.y – padding
titleEdgeInsets =UIEdgeInsetsMake(-(titleRect.origin.y - padding),
(selfWidth /2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) /2,
(titleRect.origin.y - padding),
-(selfWidth /2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) /2);
imageEdgeInsets =UIEdgeInsetsMake(0,
(selfWidth /2 - imageRect.origin.x - imageRect.size.width /2),
0,
-(selfWidth /2 - imageRect.origin.x - imageRect.size.width /2));
Copy the code
6. Keep the image centered, while the text is horizontally centered and the bottom is away from the bottom of the button
selfHeight – padding
titleRect.size.height + titleRect.origin.y
titleEdgeInsets =UIEdgeInsetsMake((selfHeight - padding - titleRect.origin.y - titleRect.size.height),
(selfWidth /2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) /2,
-(selfHeight - padding - titleRect.origin.y - titleRect.size.height),
-(selfWidth /2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) /2);
imageEdgeInsets =UIEdgeInsetsMake(0,
(selfWidth /2 - imageRect.origin.x - imageRect.size.width /2),
0,
-(selfWidth /2 - imageRect.origin.x - imageRect.size.width /2));
Copy the code
7. Keep the image centered while the text is horizontally centered and above the image
padding
titleRect.size.height + titleRect.origin.y
titleEdgeInsets =UIEdgeInsetsMake(-(titleRect.origin.y + titleRect.size.height - imageRect.origin.y + padding),
(selfWidth /2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) /2,
(titleRect.origin.y + titleRect.size.height - imageRect.origin.y + padding),
-(selfWidth /2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) /2);
imageEdgeInsets =UIEdgeInsetsMake(0,
(selfWidth /2 - imageRect.origin.x - imageRect.size.width /2),
0,
-(selfWidth /2 - imageRect.origin.x - imageRect.size.width /2));
Copy the code
8. Keep the image centered while the text is horizontally centered and below the image
padding
imageRect.origin.y + imageRect.size.height + padding
titleRect.origin.y
titleEdgeInsets =UIEdgeInsetsMake((imageRect.origin.y + imageRect.size.height - titleRect.origin.y + padding),
(selfWidth /2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) /2,
-(imageRect.origin.y + imageRect.size.height - titleRect.origin.y + padding),
-(selfWidth /2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) /2);
imageEdgeInsets =UIEdgeInsetsMake(0,
(selfWidth /2 - imageRect.origin.x - imageRect.size.width /2),
0,
-(selfWidth /2 - imageRect.origin.x - imageRect.size.width /2));
Copy the code
9. Picture on the right, text on the left, distance between the two sides of the button
In this way, the image and the text are vertically centered, which does not need to be adjusted. The left side of the text needs to be moved from titlerect.Origine.x to the left padding. The left side of the image needs to be moved from imageRect. Origin. X to selfwidth-padding-imageRect. So the code is set to:
self.titleEdgeInsets = UIEdgeInsetsMake(0,
-(titleRect.origin.x - padding),
0,
(titleRect.origin.x - padding));
self.imageEdgeInsets = UIEdgeInsetsMake(0,
(selfWidth - padding - imageRect.origin.x - imageRect.size.width),
0,
-(selfWidth - padding - imageRect.origin.x - imageRect.size.width));
Copy the code
Picture on the left, text on the right, distance from the two sides of the button margin
In this way, the vertical position of the picture and text does not need to be adjusted, but only the horizontal position of the text can be adjusted, and the adjustment method is similar to the above, but the picture is moved to the left side and the text is moved to the right. The code is set to:
self.titleEdgeInsets = UIEdgeInsetsMake(0,
(selfWidth - padding - titleRect.origin.x - titleRect.size.width),
0,
-(selfWidth - padding - titleRect.origin.x - titleRect.size.width));
self.imageEdgeInsets = UIEdgeInsetsMake(0,
-(imageRect.origin.x - padding),
0,
(imageRect.origin.x - padding));
Copy the code
I think the ten combination styles mentioned above can meet your needs. If these combination styles still cannot meet your needs, you should not use UIButton. In order to facilitate your use, I have organized the above pictures and texts into a UIButton classification method, which you can directly copy and use:
The header file:
// // UIButton+ imagetitlestyle. h // // Created by Ouyang Da on 14-7-13. // QQ: 156355113 // Github: https://github.com/youngsoft // Email: [email protected] //#import <UIKit/UIKit.h> /* The relationship between Image and text in UIButton when both Image and Title are set */ typedef NS_ENUM(NSInteger, ButtonImageTitleStyle) {ButtonImageTitleStyleDefault = 0, / / picture on the left, the words in the right, the whole center. ButtonImageTitleStyleLeft = 0, / / picture on the left, words in the right, the whole center. ButtonImageTitleStyleRight = 2, / / picture on the right, words in the left, center as a whole. ButtonImageTitleStyleTop = 3, // Image on top, text on bottom, overall center. ButtonImageTitleStyleBottom = 4, / / picture, word, the whole center. ButtonImageTitleStyleCenterTop = 5, / / the image center, the text in the distance button on the top. ButtonImageTitleStyleCenterBottom = 6, / / the image center, writing the next button at the bottom of the distance. ButtonImageTitleStyleCenterUp = 7, / / the image center, words in the pictures above. ButtonImageTitleStyleCenterDown = 8, / / the image center, words in the pictures below. ButtonImageTitleStyleRightLeft = 9, / / picture on the right, words in the left, the distance on both sides of the button margin ButtonImageTitleStyleLeftRight = 10, / / picture on the left, the words in the right, the distance on both sides of the button margins}; @interface UIButton (ImageTitleStyle) /* Adjust the layout of the text and image of the button if the title and image exist together. Padding is the spacing of the entire button and text when adjusting the layout. */ -(void)setButtonImageTitleStyle:(ButtonImageTitleStyle)style padding:(CGFloat)padding;
@end
Copy the code
Implementation file:
// // UIButton+ imagetitlestyle. m // // Created by Ouyang Brother on 14-7-13. //#import "UIButton+ImageTitleStyle.h"
@implementation UIButton (ImageTitleStyle)
-(void)setButtonImageTitleStyle:(ButtonImageTitleStyle)style padding:(CGFloat)padding
{
if(self.imageView.image ! = nil && self.titleLabel.text ! Self. titleEdgeInsets = UIEdgeInsetsZero; self.imageEdgeInsets = UIEdgeInsetsZero; CGRect imageRect = self.imageView.frame; CGRect titleRect = self.titleLabel.frame; CGFloat totalHeight = imageRect.size.height + padding + titleRect.size.height; CGFloat selfHeight = self.frame.size.height; CGFloat selfWidth = self.frame.size.width; switch (style) {case ButtonImageTitleStyleLeft:
if(padding ! = 0) { self.titleEdgeInsets = UIEdgeInsetsMake(0, padding/2, 0, -padding/2); self.imageEdgeInsets = UIEdgeInsetsMake(0, -padding/2, 0, padding/2); }break;
caseButtonImageTitleStyleRight: {// The picture is on the right, Self. titleEdgeInsets = UIEdgeInsetsMake(0, -(imageRect.sie.width + padding/2), 0, (imageRect.size.width + padding/2)); self.imageEdgeInsets = UIEdgeInsetsMake(0, (titleRect.size.width+ padding/2), 0, -(titleRect.size.width+ padding/2)); }break;
caseButtonImageTitleStyleTop: {// The picture is on the top, Self. titleEdgeInsets = UIEdgeInsetsMake(((selfHeight - totalHeight)/2 + imageRect. Size. Height + padding - titleRect.origin.y), (selfWidth/2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) / 2, -((selfHeight - totalHeight)/2 + imageRect.size.height + padding - titleRect.origin.y), -(selfWidth/2 - titleRect.origin.x - titleRect.size.width /2) - (selfWidth - titleRect.size.width) / 2); self.imageEdgeInsets = UIEdgeInsetsMake(((selfHeight - totalHeight)/2 - imageRect.origin.y), (selfWidth /2 - imageRect.origin.x - imageRect.size.width / 2), -((selfHeight - totalHeight)/2 - imageRect.origin.y), -(selfWidth /2 - imageRect.origin.x - imageRect.size.width / 2)); }break;
caseButtonImageTitleStyleBottom: {/ / picture below, in the text. self.titleEdgeInsets = UIEdgeInsetsMake(((selfHeight - totalHeight)/2 - titleRect.origin.y), (selfWidth/2 - titleRect.origin.x - titleRect.size.width / 2) - (selfWidth - titleRect.size.width) / 2, -((selfHeight - totalHeight)/2 - titleRect.origin.y), -(selfWidth/2 - titleRect.origin.x - titleRect.size.width / 2) - (selfWidth - titleRect.size.width) / 2); self.imageEdgeInsets = UIEdgeInsetsMake(((selfHeight - totalHeight)/2 + titleRect.size.height + padding - imageRect.origin.y), (selfWidth /2 - imageRect.origin.x - imageRect.size.width / 2), -((selfHeight - totalHeight)/2 + titleRect.size.height + padding - imageRect.origin.y), -(selfWidth /2 - imageRect.origin.x - imageRect.size.width / 2)); }break;
case ButtonImageTitleStyleCenterTop:
{
self.titleEdgeInsets = UIEdgeInsetsMake(-(titleRect.origin.y - padding),
(selfWidth / 2 - titleRect.origin.x - titleRect.size.width / 2) - (selfWidth - titleRect.size.width) / 2,
(titleRect.origin.y - padding),
-(selfWidth / 2 - titleRect.origin.x - titleRect.size.width / 2) - (selfWidth - titleRect.size.width) / 2);
self.imageEdgeInsets = UIEdgeInsetsMake(0,
(selfWidth / 2 - imageRect.origin.x - imageRect.size.width / 2),
0,
-(selfWidth / 2 - imageRect.origin.x - imageRect.size.width / 2));
}
break;
case ButtonImageTitleStyleCenterBottom:
{
self.titleEdgeInsets = UIEdgeInsetsMake((selfHeight - padding - titleRect.origin.y - titleRect.size.height),
(selfWidth / 2 - titleRect.origin.x - titleRect.size.width / 2) - (selfWidth - titleRect.size.width) / 2,
-(selfHeight - padding - titleRect.origin.y - titleRect.size.height),
-(selfWidth / 2 - titleRect.origin.x - titleRect.size.width / 2) - (selfWidth - titleRect.size.width) / 2);
self.imageEdgeInsets = UIEdgeInsetsMake(0,
(selfWidth / 2 - imageRect.origin.x - imageRect.size.width / 2),
0,
-(selfWidth / 2 - imageRect.origin.x - imageRect.size.width / 2));
}
break;
case ButtonImageTitleStyleCenterUp:
{
self.titleEdgeInsets = UIEdgeInsetsMake(-(titleRect.origin.y + titleRect.size.height - imageRect.origin.y + padding),
(selfWidth / 2 - titleRect.origin.x - titleRect.size.width / 2) - (selfWidth - titleRect.size.width) / 2,
(titleRect.origin.y + titleRect.size.height - imageRect.origin.y + padding),
-(selfWidth / 2 - titleRect.origin.x - titleRect.size.width / 2) - (selfWidth - titleRect.size.width) / 2);
self.imageEdgeInsets = UIEdgeInsetsMake(0,
(selfWidth / 2 - imageRect.origin.x - imageRect.size.width / 2),
0,
-(selfWidth / 2 - imageRect.origin.x - imageRect.size.width / 2));
}
break;
case ButtonImageTitleStyleCenterDown:
{
self.titleEdgeInsets = UIEdgeInsetsMake((imageRect.origin.y + imageRect.size.height - titleRect.origin.y + padding),
(selfWidth / 2 - titleRect.origin.x - titleRect.size.width / 2) - (selfWidth - titleRect.size.width) / 2,
-(imageRect.origin.y + imageRect.size.height - titleRect.origin.y + padding),
-(selfWidth / 2 - titleRect.origin.x - titleRect.size.width / 2) - (selfWidth - titleRect.size.width) / 2);
self.imageEdgeInsets = UIEdgeInsetsMake(0,
(selfWidth / 2 - imageRect.origin.x - imageRect.size.width / 2),
0,
-(selfWidth / 2 - imageRect.origin.x - imageRect.size.width / 2));
}
break;
caseButtonImageTitleStyleRightLeft: {// Picture on the right, text on the left, Self. titleEdgeInsets = UIEdgeInsetsMake(0, -(titlerect.origin.x-padding), 0, (titlerect.origin.x-padding)); self.imageEdgeInsets = UIEdgeInsetsMake(0, (selfWidth - padding - imageRect.origin.x - imageRect.size.width), 0, -(selfWidth - padding - imageRect.origin.x - imageRect.size.width)); }break;
caseButtonImageTitleStyleLeftRight: {// Picture on the left, text on the right, Self. titleEdgeInsets = UIEdgeInsetsMake(0, (selfWidth-padding-titlerect.origin. X-titlerect.size. Width), 0, -(selfWidth - padding - titleRect.origin.x - titleRect.size.width)); self.imageEdgeInsets = UIEdgeInsetsMake(0, -(imageRect.origin.x - padding), 0, (imageRect.origin.x - padding)); }break;
default:
break; }}else {
self.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
self.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
}
}
@end
Copy the code
The above methods setButtonImageTitleStyle (ButtonImageTitleStyle) style Padding :(CGFloat) Padding should be called after the UIButton object is created and a specific frame value or automatic layout constraint size is specified, and setTitle:forState: and setImage:forSate: are called:
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0,0,100,100)];
[button setTitle:@"Test text" forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:@"test"] forState:UIControlStateNormal];
[button setButtonImageTitleStyle:ButtonImageTitleStyleTop padding:10];
Copy the code
In addition, if you want the image and text in your button as a whole to be horizontal left, or horizontal right, or vertical up or vertical down, you can use UIButton’s native (UIControl) property:
@property(nonatomic) UIControlContentVerticalAlignment contentVerticalAlignment; // how to position content vertically inside control. default is center
@property(nonatomic) UIControlContentHorizontalAlignment contentHorizontalAlignment; // how to position content hozontally inside control. default is center
Copy the code
These two properties set the overall position of the button, vertical and horizontal adjustment, the specific Settings are up to the reader to practice.