UIButton实现各种图文结合的效果以及原理

5,060 阅读12分钟

iOS的UIButton是一个非常常见而且常用的控件,我们一般用他来实现某个功能的提交以及选择操作。我们可以建立只有文字的Button,也可以建立只有图片的Button,具体的需求要看界面设计的具体情况。有时候我们希望应用的界面元素是丰富多彩的,有时候希望建立一个图文结合的控件来响应用户的手势操作,因此建立一个即有图片也有文字的按钮来实现功能,这个只需要分别调用UIButton的setTitle:forState:setImage:forSate:两个方法就可以实现具有图片和文字功能的按钮。但是系统默认的图文结合的按钮布局是:图片在左边而文字在右边,而且整体水平和垂直居中。比如下面这个图文按钮:

默认的图文按钮
但是有的时候我们又希望图片在右边而文字在左边;或者图片在上边而文字在下面;或者图片在按钮的中间而文字在图片的下面等等,但我们又不想放弃使用按钮这个控件,这时候怎么办? 事件总是能找到解决方法的, 有的人会先建立一个按钮控件铺在下面,而在上面分别覆盖一个UIImageViewUILabel来实现;而有的人则干脆在UIButton上建立一个UIImageViewUILabel两个子视图;而有的人则不会用UIButton来实现图文结合的功能。 前面说的几个方法看起来有效,也确实会解决问题,但缺点是代码量会增加,而且必须同时管理UIButton, UIImageView, UILabel这三个整体,如果哪天产品还希望有一个按钮按下高亮或者按下阴影效果时,你可能又要重新编写代码实现需求了。 那么我们是否要放弃UIButton呢?答案是否定的,其实UIButton本身是可以支持各种图文结合的,既然UIButton上能同时显示图片和文字,那就可以肯定的说UIButton里面本身一定有一个UIImageView和*UILabel8子视图。UIButton本身就是一个复合控件,他分别提供了两个属性:

@property(nonatomic,readonly,retain)UILabel     *titleLabel NS_AVAILABLE_IOS(3_0);
@property(nonatomic,readonly,retain)UIImageView *imageView  NS_AVAILABLE_IOS(3_0);

需要注意的是这两个属性必须要调用完setTitle:forSate:setImage:forSate:后才能获取到,否则有可能会返回nil。 其中的 titleLabel是用来保存文字的而imageView是用来保存图片的。那既然UIButton本身就带有一个图片控件和文本控件,那是不是我们只要分别通过调整子控件的frame值就能实现我们想要的图片文字的任何布局呢? 答案是否定的。实验证明通过设置titleLabel、imageViewframe值根本不会改变按钮里面图片在左而文字在右的格局。 要想实现功能就必须使用另外两个属性:

@property(nonatomic)         UIEdgeInsets titleEdgeInsets;   // default is UIEdgeInsetsZero
@property(nonatomic)         UIEdgeInsets imageEdgeInsets;   // default is UIEdgeInsetsZero

这两个属性是分别用来调整按钮中文本的偏移缩进以及图片的偏移缩进的,他们都是一个UIEdgeInsets对象,默认的值都是0,也就是默认的值都是0的情况下按钮的图片和文字垂直居中,而且图片在左边文字在右边,而且图片文本整体水平居中。而我们则可以通过调整titleEdgeInsetsimageEdgeInsets的值来实现我们想要的任何图文布局的情况,甚至我们希望图片和文字之间还要保留一些间隔的情况。怎么调整? 调整多少为最合适?

在调整之前我们先定义几个特定的变量值:

: CGRect titleRect = titleLabel.frame; //文本控件在按钮中的frame值。 CGRect imageRect = imageView.frame; //图片控件在按钮中的frame值。 CGFloat padding; //用于指定文本和图片的间隔值。 CGFloat selfWidth; //按钮控件的宽度 CGFloat selfHeight; //按钮控件的高度 CGFloat totalHeight=titleRect.size.height+padding+imageRect.size.height; //图文上下布局时所占用的总高度,注意这里也算上他们之间的间隔值padding

我们可以通过更改按钮的titleEdgeInsetsimageEdgeInsets的值调整文本和图片的位置。如果我们想往右移动20的话,那么就应该同时设置UIEdgeInsets的left=20, right=-20,而如果我们想往上移动20的话,那么就应该应该同时设置UIEdgeInsets的top=-20,bottom=20。下面我们就分别通过调整按钮的titleEdgeInsetsimageEdgeInsets的值来实现各种图文结合的效果:

##一、图片在左,文字在右,整体居中,调整间距

图片在左,文字在右,整体居中,设置间距
这种方式是按钮默认的图文布局方式,因为要调整图片和文本的间距,所以只需要文本右移padding/2而图片左移padding/2值就可以了。设置的代码为:

  titleEdgeInsets =UIEdgeInsetsMake(0,
                                     padding/2,
                                     0,
                                     -padding/2);
                
  imageEdgeInsets = UIEdgeInsetsMake(0,
                                     -padding/2,
                                     0,
                                     padding/2);

##二、图片在右,文字在左,整体居中

图片在右,文字在左,整体居中
要实现这种布局只需要将文字往左偏移图片的宽度并且再往左偏移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));

##三、图片在上,文字在下,整体居中

图片在上,文字在下,整体居中
这种布局下当图片和文字要求垂直居中后,新的图片的顶部位置应该等于*(selfHeight - totalHeight)/2*, 因此垂直需要偏移的值就是新的位置减去原来的位置imageRect.origin.y;而新的图片的水平中心点要等于selfWidth/2,而原来的图片的水平中心点等于imageRect.origin.x + imageRect.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,所以上面的实现将文本移到中间后还需要分别向两边进行拉伸*(selfWith - titleRect.size.width)/2*来保证文本填充满所有的按钮区域,在下面的各种样式中凡是文字和图片垂直居中的情况下都要考虑这种情况 设置的代码为:

  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));

##四、图片在下,文字在上,整体居中

图片在下,文字在上,整体居中
这种布局就是上面的文字和图片位置调换,因此设置代码为:

  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));

##五、图片保持居中,而文字左右居中且顶部距离按钮顶部

图片保持居中,而文字左右居中且顶部距离按钮顶部
这种方式要求图片在按钮中居中,而文字则要求左右居中而垂直方向位置则是距离按钮顶部的间隔值。 上面因为描述了水平居中的调整,因此这里就不介绍了,只介绍垂直方向的调整。 因为要求图片要垂直居中,因此不需要调整垂直偏移。而文本则要调整为距离顶部的间隔值,也就是新的文本的顶部值等于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));

##六、图片保持居中,而文字水平居中且底部距离按钮底部

图片保持居中,而文字水平居中且底部距离按钮底部
这种方式要求图片在按钮居中,而文字则要求左右居中而垂直方向的底部位置则是距离按钮底部的间隔值。图片的调整上面有介绍,而文字的水平调整上面也有说到,这里面只说文字的垂直调整。文字新的底部位置等于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));

##七、图片保持居中,而文字水平居中并且在图片的上面

图片保持居中,而文字水平居中并且在图片的上面
这种方式要求图片在按钮居中,而文字则要求左右居中并且在垂直在图片的上面并保留出padding的间隔。 图片的偏移上面有说到,而文字的水平偏移上面也有说到,这里只说垂直偏移,文字新的底部位置等于图片的顶部位置 - 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));

##八、图片保持居中,而文字水平居中并且在图片的下面

图片保持居中,而文字水平居中并且在图片的下面
这种方式要求图片在按钮居中,而文字则要求左右居中并且垂直在图片的下面并保留出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));

##九、图片在右,文字在左,距离按钮两边边距

图片在右,文字在左,距离按钮两边边距

在这种方式中,图片和文本都是垂直居中对齐,这部分是不需要调整的,而文本的左边则需要由原来的titleRect.origin.x移动到左边padding的位置,而图片的左边则需要由原来的imageRect.origin.x移动到selfWidth - padding - imageRect.size.width位置。因此代码设置为:

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));

##十、图片在左,文字在右,距离按钮两边边距

图片在左,文字在右,距离按钮两边边距

这种方式中,图片和文字的垂直位置不需要调整,而只需要将图文的水平位置调整即可,而调整的方法和上面的相似,只是图片移到左边儿文字移到右边而已。代码设置为:

 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));


前面说的的十种图文结合样式,我想应该可以满足您的需求了,如果这些图文结合的样式还是无法满足您的需求时则您还是别用UIButton了。 为了方便大家的使用,我把上面的图文结合样式整理成了一个UIButton的分类方法,大家可以直接拷贝使用:

头文件:

//  
//  UIButton+ImageTitleStyle.h  
//  
//  Created by 欧阳大哥 on 14-7-13.  
//  QQ:156355113
//  Github:  https://github.com/youngsoft
//  Email:  obq0387_cn@sina.com
//  
  
#import <UIKit/UIKit.h>  
  
/* 
 针对同时设置了Image和Title的场景时UIButton中的图片和文字的关系 
 */  
typedef NS_ENUM(NSInteger, ButtonImageTitleStyle ) {  
    ButtonImageTitleStyleDefault = 0,       //图片在左,文字在右,整体居中。  
    ButtonImageTitleStyleLeft  = 0,         //图片在左,文字在右,整体居中。  
    ButtonImageTitleStyleRight     = 2,     //图片在右,文字在左,整体居中。  
    ButtonImageTitleStyleTop  = 3,          //图片在上,文字在下,整体居中。  
    ButtonImageTitleStyleBottom    = 4,     //图片在下,文字在上,整体居中。  
    ButtonImageTitleStyleCenterTop = 5,     //图片居中,文字在上距离按钮顶部。  
    ButtonImageTitleStyleCenterBottom = 6,  //图片居中,文字在下距离按钮底部。  
    ButtonImageTitleStyleCenterUp = 7,      //图片居中,文字在图片上面。  
    ButtonImageTitleStyleCenterDown = 8,    //图片居中,文字在图片下面。  
    ButtonImageTitleStyleRightLeft = 9,     //图片在右,文字在左,距离按钮两边边距
    ButtonImageTitleStyleLeftRight = 10,    //图片在左,文字在右,距离按钮两边边距
};  
  
@interface UIButton (ImageTitleStyle)  
  
/* 
 调整按钮的文本和image的布局,前提是title和image同时存在才会调整。 
 padding是调整布局时整个按钮和图文的间隔。 
  
 */  
-(void)setButtonImageTitleStyle:(ButtonImageTitleStyle)style padding:(CGFloat)padding;  
  
@end  

实现文件:

//
//  UIButton+ImageTitleStyle.m
//
//  Created by 欧阳大哥 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 != nil)
    {
        
        //先还原
        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;
            case ButtonImageTitleStyleRight:
            {
                //图片在右,文字在左
                self.titleEdgeInsets = UIEdgeInsetsMake(0,
                                                        -(imageRect.size.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;
            case ButtonImageTitleStyleTop:
            {
                //图片在上,文字在下
                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;
            case ButtonImageTitleStyleBottom:
            {
                //图片在下,文字在上。
                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;
            case ButtonImageTitleStyleRightLeft:
            {
                 //图片在右,文字在左,距离按钮两边边距
                
                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;
                
            case ButtonImageTitleStyleLeftRight:
            {
                //图片在左,文字在右,距离按钮两边边距
                
                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

上面的方法setButtonImageTitleStyle:(ButtonImageTitleStyle)style padding:(CGFloat)padding请在建立完UIButton对象并且指定一个具体的frame值或者自动布局的约束尺寸后,并且调用setTitle:forState:setImage:forSate:后再调用:

UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0,0,100,100)];
[button setTitle:@"测试文本" forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:@"test"] forState:UIControlStateNormal];
[button setButtonImageTitleStyle:ButtonImageTitleStyleTop padding:10];

另外如果你想要你的按钮中的图片和文字整体的水平居左,或者水平居右,或者垂直居上或者垂直居下则可以用UIButton的原生(UIControl)属性:

@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

这两个属性来设置按钮的垂直和水平的整体位置的调整,具体设置则读者自行去实践吧。