UIButton自定义图片文字位置总结

UIButton的默认显示样式是图片居左,文字居右,如下图1:

但是有时候我们根据需求需要调整按钮中图片和标题的位置,最常见的就是图片居上,文字居下显示的按钮,如下图2所示:

实现这种居中显示的图上文下的按钮方式有很多,比如最简单的方法:自定义View,上面放一个UIButton一个UILabel子控件。

这里我们介绍其他方法来实现UIButton图片和标题的位置调整:

  • 一种是通过类别(Category)调整位置;
  • 一种是通过继承重写系统方法调整位置。

通过类别(Category)调整位置

通过类别的方法修改图片标题的位置主要是用了UIButton的两个位置属性:titleEdgeInsetsimageEdgeInsets。通过修改按钮中imagetitleedgeInsets来改变相对位置。

@property(nonatomic)          UIEdgeInsets titleEdgeInsets;                // default is UIEdgeInsetsZero
@property(nonatomic)          UIEdgeInsets imageEdgeInsets;                // default is UIEdgeInsetsZero
复制代码

UIEdgeInsets有四个参数:top, left, bottom, right,分别代表上左下右的偏移量。

top : 为正数的时候,是往下偏移,为负数的时候往上偏移;
left : 为正数的时候往右偏移,为负数的时候往左偏移;
bottom : 为正数的时候往上偏移,为负数的时候往下偏移;
right :为正数的时候往左偏移,为负数的时候往右偏移;

修改按钮中image和title位置的关键就是正确的设置这两个属性值的参数,网上很多介绍的方法里写的都是固定参数,如果每次使用都要去计算的话那就太麻烦了,这里我们通过获取image和title的size来设定偏移量,实现方法的通用。这也是创建一个UIButton的category的原因,方便以后的复用。

下面贴上category的代码,其中计算titleEdgeInsetsimageEdgeInsets的代码是最核心的地方,具体的计算思路可以从代码里看出来,就不文字介绍了。这里的计算思路是最关键的地方,只要知道怎么计算,就可以使用UIButton实现其他图文效果,而不止是图上文下的居中效果。

#import <UIKit/UIKit.h>

@interface UIButton (ZXCenterButton)
/**
 图片居上,文字居下,图文居中按钮

 @param spaceBetween image和label之间的间距,若设为nil则距离为0
 @param fontSize 标题字体大小,若设为nil则为默认字体大小17
 */
-(instancetype)initCenterBtnWithFrame:(CGRect)frame
                         spaceBetween:(NSNumber*)spaceBetween
                           imageNamed:(NSString *)imageName
                                title:(NSString *)title
                             fontSize:(NSNumber*)fontSize;

@end
复制代码
#import "UIButton+ZXCenterButton.h"

@implementation UIButton (ZXCenterButton)

-(instancetype)initCenterBtnWithFrame:(CGRect)frame spaceBetween:(NSNumber*)spaceBetween imageNamed:(NSString *)imageName title:(NSString *)title fontSize:(NSNumber*)fontSize{

    if (self = [super initWithFrame:frame]) {
        CGFloat font = fontSize == nil ? 17 : [fontSize floatValue];
        [self setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
        [self setTitle:title forState:UIControlStateNormal];
        self.titleLabel.font = [UIFont systemFontOfSize:font];

        //  图片的宽高
        CGFloat imageW = self.imageView.frame.size.width;
        CGFloat imageH = self.imageView.frame.size.height;
       
        //  计算标题的size
        CGSize titleSize = [self string:title sizeWithFont:[UIFont systemFontOfSize:font]];
        
        // 图片+标题的总宽高
        CGFloat totalW = imageW + titleSize.width;
        CGFloat totalH = imageH + titleSize.height + spaceBetween.floatValue;
        // 设置按钮图片偏移
        [self setImageEdgeInsets:UIEdgeInsetsMake(-(totalH/2 - imageH/2), totalW/2 - imageW/2, (totalH/2 - imageH/2), -(totalW/2 - imageW/2))];
        // 设置按钮标题偏移
        [self setTitleEdgeInsets:UIEdgeInsetsMake((totalH/2 - titleSize.height/2), -(totalW/2 - titleSize.width/2), -(totalH/2 - titleSize.height/2), totalW/2 - titleSize.width/2)];
    }
    return self;
}

//  根据文字的长度、字体  来计算size
- (CGSize)string:(NSString *)string sizeWithFont:(UIFont *)font{
    NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
    attrs[NSFontAttributeName] = font;
    CGSize maxSize = CGSizeMake(MAXFLOAT, MAXFLOAT);
    return [string boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;
}

@end
复制代码

这种方法使用的时候注意Button的宽度设置和title的string长度,如果按钮宽度太小,标题的string太长,title无法全部显示时,label的宽度计算会出现偏差造成布局不居中。所以使用的时候要确保title能完全显示


通过继承调整位置

通过继承的方法调整image和label的位置其实也有两种实现方法:

  • 一种是在- (void)layoutSubviews里面重写self.titleLabel.frameself.imageView.frame的rect值;
  • 另一种就是本文要介绍的,重写系统方法改变title和image的布局。

通过继承需要重写的两个系统方法是:

 Objective-C
- (CGRect)titleRectForContentRect:(CGRect)contentRect;  
- (CGRect)imageRectForContentRect:(CGRect)contentRect;
复制代码

具体实现方法直接见代码:

- (CGRect)titleRectForContentRect:(CGRect)contentRect
{
    CGRect titleRect = CGRectMake(0, CGRectGetHeight(self.bounds)/3 * 2, CGRectGetWidth(self.bounds),CGRectGetHeight(self.bounds)/3);
    return titleRect;
}

- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
    CGFloat width = CGRectGetWidth(self.bounds);
    //  图片占按钮高度的2/3
    CGRect imageRect = CGRectMake(0, 0, width, CGRectGetHeight(self.bounds)/3 * 2);

    return imageRect;
}
复制代码

使用这种方法的时候记得按钮的标题需要设置为居中,此方法来自我朋友的一篇文章,详情请移步,谢谢。


总结

解决问题的方法有各种各样,重要的是能解决问题,每个人的偏好都不一样。本文介绍的两种方法,第一种通过类别修改位置需要对UIEdgeInsets属性理解透彻而且需要有很好的图形位置想象能力,否则自己很容易搞晕,但是类别的好处是以后直接拿来用就可以,不用再创建类复制粘贴了;第二种计算就相对来说比较简单了,但是需要创建类来继承,复制粘贴代码。大家选择适合自己的就好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值