UIButton 设置图片和文字布局样式

引言:

日常开发中经常遇到 图片在上、文字描述在下的按钮样式,可以通过修改按钮文字图片布局来实现。


# 一. 通过分类方式实现

该方式是通过设置 imageViewtitleLabeltitleEdgeInsets 属性来实现的。

  • 如果只有 title,那它上下左右都是相对于button的,image也是一样;
  • 如果同时有image和label,那这时候image的上左下是相对于button,右边是相对于label的;title的上右下是相对于button,左边是相对于image的。

# 1. UIButton+Custom.h


#import <UIKit/UIKit.h>

/** 按钮文字图片布局的样式 */
typedef NS_ENUM(NSUInteger, LCButtonLayoutStyle) {
	LCButtonLayoutStyleImageTop, // image在上,label在下
	LCButtonLayoutStyleImageLeft, // image在左,label在右
	LCButtonLayoutStyleImageBottom, // image在下,label在上
	LCButtonLayoutStyleImageRight // image在右,label在左
};

@interface UIButton (Custom)

/**
 * 设置button的titleLabel和imageView的布局样式,及间距
 *
 * @param style titleLabel和imageView的布局样式
 * @param space titleLabel和imageView的间距
 */
-(void)lc_setupImageAndTitleLayoutWithStyle:(LCButtonLayoutStyle)style space:(CGFloat)space;

@end

# 2. UIButton+Custom.m


#import "UIButton+Custom.h"

@implementation UIButton (Custom)

-(void)lc_setupImageAndTitleLayoutWithStyle:(LCButtonLayoutStyle)style space:(CGFloat)space;{
   
    // 1. 得到imageView和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) {
        // 由于iOS8中titleLabel的size为0,用下面的这种设置
        labelWidth = self.titleLabel.intrinsicContentSize.width;
        labelHeight = self.titleLabel.intrinsicContentSize.height;
    } else {
        labelWidth = self.titleLabel.frame.size.width;
        labelHeight = self.titleLabel.frame.size.height;
    }

    // 2. 声明全局的imageEdgeInsets和labelEdgeInsets
    UIEdgeInsets imageEdgeInsets = UIEdgeInsetsZero;
    UIEdgeInsets labelEdgeInsets = UIEdgeInsetsZero;

    // 3. 根据style和space得到imageEdgeInsets和labelEdgeInsets的值
    switch (style) {
        case LCButtonLayoutStyleImageTop:{
            imageEdgeInsets = UIEdgeInsetsMake(-labelHeight-space/2.0, 0, 0, -labelWidth);
            labelEdgeInsets = UIEdgeInsetsMake(0, -imageWith, -imageHeight-space/2.0, 0);
        } break;
        
        case LCButtonLayoutStyleImageLeft:{
            imageEdgeInsets = UIEdgeInsetsMake(0, -space/2.0, 0, space/2.0);
            labelEdgeInsets = UIEdgeInsetsMake(0, space/2.0, 0, -space/2.0);
        } break;

        case LCButtonLayoutStyleImageBottom:{
            imageEdgeInsets = UIEdgeInsetsMake(0, 0, -labelHeight-space/2.0, -labelWidth);
            labelEdgeInsets = UIEdgeInsetsMake(-imageHeight-space/2.0, -imageWith, 0, 0);
        } break;

        case LCButtonLayoutStyleImageRight: {
            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. 赋值
    self.titleEdgeInsets = labelEdgeInsets;
    self.imageEdgeInsets = imageEdgeInsets;
}
@end

# 二. 通过子类方式实现

该方式主要是 重写- (void)layoutSubviews方法, 对 imageView 和 titleLabel 的 frame 进行重新布局。


/**
 * 设置button的titleLabel和imageView的布局样式,及间距
 */
-(void)lc_setupImageAndTitleLayoutWithStyle:(LCButtonLayoutStyle)style imageWidthScale:(CGFloat)scale space:(CGFloat)space{

    self.space = space;
    self.scale = scale;
    
    switch (style) {
        case LCButtonLayoutStyleImageRight: // 图片在右
            self.layoutStyle = LCButtonLayoutStyleImageRight;
        break;

        case LCButtonLayoutStyleImageLeft: // 图片在左
            self.layoutStyle = LCButtonLayoutStyleImageLeft;
        break;
        
        case LCButtonLayoutStyleImageTop: // 图片在上
            self.layoutStyle = LCButtonLayoutStyleImageTop;
        break;
        
        case LCButtonLayoutStyleImageBottom: // 图片在下
            self.layoutStyle = LCButtonLayoutStyleImageBottom;
        break;
        default:
        break;
    }
}

// 重写layoutSubviews方法,手动设置按钮子控件的位置
- (void)layoutSubviews {

    [super layoutSubviews];


    CGFloat labelWidth = 0.0;
    CGFloat labelHeight = 0.0;

    if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
// 由于iOS8中titleLabel的size为0,用下面的这种设置
        labelWidth = self.titleLabel.intrinsicContentSize.width;
        labelHeight = self.titleLabel.intrinsicContentSize.height;
        
    } else {
    
        labelWidth = self.titleLabel.frame.size.width;
        labelHeight = self.titleLabel.frame.size.height;
    }


    self.titleLabel.bs_width = labelWidth;
    self.titleLabel.bs_height = labelHeight;
    
    switch (self.layoutStyle) {
        case LCButtonLayoutStyleImageRight: // 图片在右
        {
            self.titleLabel.bs_x = self.space / 2;
            self.titleLabel.bs_y = (self.bs_height - labelHeight )/2;

            self.imageView.bs_width = self.bs_height*self.scale;
            self.imageView.bs_height = self.imageView.bs_width;
            self.imageView.bs_x = CGRectGetMaxX(self.titleLabel.frame) + self.space;
            self.imageView.bs_y = (self.bs_height - self.imageView.bs_height) / 2;
        } break;

        case LCButtonLayoutStyleImageLeft: // 图片在左
        {
            self.imageView.bs_width = self.bs_height*self.scale;
            self.imageView.bs_height = self.imageView.bs_width;
            self.imageView.bs_x = self.space;
            self.imageView.bs_y = (self.bs_height - self.imageView.bs_width) / 2;

            self.titleLabel.bs_x = CGRectGetMaxX(self.imageView.frame) + self.space;
            self.titleLabel.bs_y = (self.bs_height - labelHeight )/2;
        } break;

        case LCButtonLayoutStyleImageTop: // 图片在上
        {
            self.imageView.bs_width = self.bs_width * self.scale;
            self.imageView.bs_height = self.imageView.bs_width;
            self.imageView.bs_x = (self.bs_width - self.imageView.bs_width) / 2.0;
            self.imageView.bs_y = self.space;
            self.titleLabel.bs_x = (self.bs_width - labelWidth) / 2.0;
            self.titleLabel.bs_y = CGRectGetMaxY(self.imageView.frame) + self.space;
        } break;

        case LCButtonLayoutStyleImageBottom: // 图片在下
        {
            self.titleLabel.bs_x = (self.bs_width - labelWidth) / 2.0;
            self.titleLabel.bs_y = self.space / 2;
            self.imageView.bs_width = self.bs_width * self.scale;
            self.imageView.bs_height = self.imageView.bs_width;
            self.imageView.bs_x = (self.bs_width - self.imageView.bs_width) / 2.0;
            self.imageView.bs_y = CGRectGetMaxY(self.titleLabel.frame) + self.space;
        } break;
        default:
        break;
    }
}