UIButton的图文排列

图文结合

通过 setTitle:forState: 和 setImage:forState: 这两个方法设置了 UIButton 的 标题和图片之后,可以通过以下两个属性访问代表 UIButton 中标题和图片的两个子控件:

@property(nullable, nonatomic,readonly,strong) UILabel     *titleLabel;
@property(nullable, nonatomic,readonly,strong) UIImageView *imageView;

UIControlContentVerticalAlignment

UIControlContentVerticalAlignment控制的是UIButtonimagetitle在竖直方向的对齐方式,其值有topbottomcenterfill。当指定为fill时,图片会在竖直方向被拉伸填满UIButton的高度。


// UIButton的image和title在竖直方向的对齐方式
typedef NS_ENUM(NSInteger, UIControlContentVerticalAlignment) {
UIControlContentVerticalAlignmentCenter = 0,
UIControlContentVerticalAlignmentTop = 1,
UIControlContentVerticalAlignmentBottom = 2,
UIControlContentVerticalAlignmentFill = 3,
};

UIControlContentHorizontalAlignment

UIControlContentHorizontalAlignment控制的则是水平方向的对齐方式。其值有leftrightcenterfill。当指定为fill时,图片并没有在水平方向将UIButton充满,而是在右侧留出了一定距离,这个距离应该是title的宽度,但是title实际上也没有乖乖的跑到那段空隙去,而是和image重叠了


typedef NS_ENUM(NSInteger, UIControlContentHorizontalAlignment) {
UIControlContentHorizontalAlignmentCenter = 0,
UIControlContentHorizontalAlignmentLeft = 1,
UIControlContentHorizontalAlignmentRight = 2,
UIControlContentHorizontalAlignmentFill = 3,
};

  • UIEdgeInsets

使用 insets 来添加或删除你自定义(或系统的)按钮内容周围空间,你可以单独为按钮标题(titleEdgeInsets)、图片(imageEdgeInsets)或同时为标题和图片(contentEdgeInsets)指定 insets 值。应用时,insets 影响了按钮的相应内容矩形,由Auto Layout引擎用于确定按钮的位置。


@property(nonatomic)          UIEdgeInsets contentEdgeInsets;           
@property(nonatomic) UIEdgeInsets titleEdgeInsets;
@property(nonatomic) UIEdgeInsets imageEdgeInsets;

默认按钮布局

创建一个图片+标题的按钮:

// 创建自定义类型按钮
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(80, 180, 150, 150);
// 设置按钮的背景颜色
button.backgroundColor = [UIColor honeydewColor];
// 设置按钮的标签文字
[button setTitle:@"Tap it" forState:UIControlStateNormal];
button.titleLabel.backgroundColor = [UIColor skyBlueColor];
// 设置按钮图片
UIImage *image = [UIImage imageNamed:@"buttonImage"];
[button setImage:image forState:UIControlStateNormal];
[self.view addSubview:button];

默认情况下:图片在左边而文字在右边,而且整体水平和垂直居中

这是一个 UIButton 范畴(Category) 类,用于处理图文结合

  • UIButton+ImageTitleStyle.h 文件
#import <UIKit/UIKit.h>

@interface UIButton (ImageTitleStyle)

//上下居中,图片在上,文字在下
- (void)verticalCenterImageAndTitle:(CGFloat)spacing;
- (void)verticalCenterImageAndTitle; //默认6.0

//左右居中,文字在左,图片在右
- (void)horizontalCenterTitleAndImage:(CGFloat)spacing;
- (void)horizontalCenterTitleAndImage; //默认6.0

//左右居中,图片在左,文字在右
- (void)horizontalCenterImageAndTitle:(CGFloat)spacing;
- (void)horizontalCenterImageAndTitle; //默认6.0

//文字居中,图片在左边
- (void)horizontalCenterTitleAndImageLeft:(CGFloat)spacing;
- (void)horizontalCenterTitleAndImageLeft; //默认6.0

//文字居中,图片在右边
- (void)horizontalCenterTitleAndImageRight:(CGFloat)spacing;
- (void)horizontalCenterTitleAndImageRight; //默认6.0

@end

  • UIButton+ImageTitleStyle.m 文件
#import "UIButton+ImageTitleStyle.h"

@implementation UIButton (ImageTitleStyle)

#pragma mark - 上下居中,图片在上,文字在下
- (void)verticalCenterImageAndTitle:(CGFloat)spacing
{
// get the size of the elements here for readability
CGSize imageSize = self.imageView.frame.size;
CGSize titleSize = self.titleLabel.frame.size;

// lower the text and push it left to center it
self.titleEdgeInsets = UIEdgeInsetsMake(0.0, - imageSize.width, - (imageSize.height + spacing/2), 0.0);

// the text width might have changed (in case it was shortened before due to
// lack of space and isn't anymore now), so we get the frame size again
titleSize = self.titleLabel.frame.size;

// raise the image and push it right to center it
self.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing/2), 0.0, 0.0, - titleSize.width);
}

- (void)verticalCenterImageAndTitle
{
const int DEFAULT_SPACING = 6.0f;
[self verticalCenterImageAndTitle:DEFAULT_SPACING];
}


#pragma mark - 左右居中,文字在左,图片在右
- (void)horizontalCenterTitleAndImage:(CGFloat)spacing
{
// get the size of the elements here for readability
CGSize imageSize = self.imageView.frame.size;
CGSize titleSize = self.titleLabel.frame.size;

// lower the text and push it left to center it
self.titleEdgeInsets = UIEdgeInsetsMake(0.0, - imageSize.width, 0.0, imageSize.width + spacing/2);

// the text width might have changed (in case it was shortened before due to
// lack of space and isn't anymore now), so we get the frame size again
titleSize = self.titleLabel.frame.size;

// raise the image and push it right to center it
self.imageEdgeInsets = UIEdgeInsetsMake(0.0, titleSize.width + spacing/2, 0.0, - titleSize.width);
}

- (void)horizontalCenterTitleAndImage
{
const int DEFAULT_SPACING = 6.0f;
[self horizontalCenterTitleAndImage:DEFAULT_SPACING];
}

#pragma mark - 左右居中,图片在左,文字在右
- (void)horizontalCenterImageAndTitle:(CGFloat)spacing;
{
// get the size of the elements here for readability
// CGSize imageSize = self.imageView.frame.size;
// CGSize titleSize = self.titleLabel.frame.size;

self.titleEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, - spacing/2);
self.imageEdgeInsets = UIEdgeInsetsMake(0.0, - spacing/2, 0.0, 0.0);
}

- (void)horizontalCenterImageAndTitle;
{
const int DEFAULT_SPACING = 6.0f;
[self horizontalCenterImageAndTitle:DEFAULT_SPACING];
}

#pragma mark - 文字居中,图片在左边
- (void)horizontalCenterTitleAndImageLeft:(CGFloat)spacing
{
// get the size of the elements here for readability
// CGSize imageSize = self.imageView.frame.size;
// CGSize titleSize = self.titleLabel.frame.size;

self.imageEdgeInsets = UIEdgeInsetsMake(0.0, - spacing, 0.0, 0.0);
}

- (void)horizontalCenterTitleAndImageLeft
{
const int DEFAULT_SPACING = 6.0f;
[self horizontalCenterTitleAndImageLeft:DEFAULT_SPACING];
}

#pragma mark - 文字居中,图片在右边
- (void)horizontalCenterTitleAndImageRight:(CGFloat)spacing
{
// get the size of the elements here for readability
CGSize imageSize = self.imageView.frame.size;
CGSize titleSize = self.titleLabel.frame.size;

// lower the text and push it left to center it
self.titleEdgeInsets = UIEdgeInsetsMake(0.0, - imageSize.width, 0.0, 0.0);

// the text width might have changed (in case it was shortened before due to
// lack of space and isn't anymore now), so we get the frame size again
titleSize = self.titleLabel.frame.size;

// raise the image and push it right to center it
self.imageEdgeInsets = UIEdgeInsetsMake(0.0, titleSize.width + imageSize.width + spacing, 0.0, - titleSize.width);
}

- (void)horizontalCenterTitleAndImageRight
{
const int DEFAULT_SPACING = 6.0f;
[self horizontalCenterTitleAndImageRight:DEFAULT_SPACING];
}

1. 上下居中,图片在上,文字在下


[button verticalCenterImageAndTitle:10.0f];

2. 左右居中,文字在左,图片在右


[button horizontalCenterTitleAndImage:10.0f];

3. 左右居中,图片在左,文字在右

[button horizontalCenterImageAndTitle:10.0f];

通过布局子视图方法:

当 UIButton 是固定大小时,使用上面的方法无法设置按钮中的图片相对于整个按钮的大小。

  • 图片在上、文字在下
- (void) layoutSubviews {
[super layoutSubviews];
// 修改button内image和label的位置
self.imageView.y = self.height * 0.15;
self.imageView.width = self.width * 0.5;
self.imageView.height = self.imageView.width;
self.imageView.centerX = self.width * 0.5;

self.titleLabel.x = 0;
self.titleLabel.y = self.imageView.bottom;
self.titleLabel.width = self.width;
self.titleLabel.height = self.height - self.imageView.bottom;
}

显示/隐藏密码按钮

- (UIButton *)showPasswordButton {
if (!_showPasswordButton) {
_showPasswordButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_showPasswordButton setImage:[UIImage imageNamed:@"login_pwd_hide"]
forState:UIControlStateNormal];
[_showPasswordButton setImage:[UIImage imageNamed:@"login_pwd_show"]
forState:UIControlStateSelected];
[_showPasswordButton setSelected:NO];
[_showPasswordButton addTarget:self
action:@selector(showPasswordButtonDidClicked:)
forControlEvents:UIControlEventTouchUpInside];
}
return _showPasswordButton;
}

- (void)showPasswordButtonDidClicked:(id)sender {
self.passwordTextField.secureTextEntry = !self.passwordTextField.secureTextEntry;
[self.showPasswordButton setSelected:!self.passwordTextField.secureTextEntry];
}



0 个评论

要回复文章请先登录注册