UIButton的titleEdgeInsets和imageEdgeInsets属性

转载于  http://www.haogongju.net/art/2359703

uiButton控件上自带了一个uiLabel类型的子控件和一个uiImageView类型的子控件,如果可以正确使用他们的edgeInsets属性,就能把button设置成我们想要的样子。

  关于titleEdgeInsets,苹果文档的解释是:The inset or outset margins for the rectangle around the button’s title text,而且imageEdgeInsets也是类似,都没有讲怎么设。事实上,这两个东西是有联系的,常常会造成困惑:我只设了其中一个的edgeInsets,为什么button上的图片和文字布局都变了?

  这里是一个同事花一个下午的时间,专门写一段button的代码,分析数据,总结出来的小规律,并不权威,但是挺好用的,总结出来分享一下。

      默认情况下,imageEdgeInsets和titleEdgeInsets都是0。先不考虑height,

  if (button.width小于imageView上image的width){图像会被压缩,文字不显示}

      if (button.width < imageView.width + label.width){图像正常显示,文字显示不全}

      if (button.width >= imageView.width + label.width){图像和文字都居中显示,imageView在左,label在右,中间没有空隙}  

  实际app应用中,通常会已知如下参数,布局button

  button的width:BUTTON_WIDTH

  button上控件imageView的的图片为image

  label上的文字为:@“这是一个测试”

  为了不看着头疼,不写那么多的常量了,以具体的数字来举例吧,我们想让imageView在前,label在后,居中显示,imageView在button上离左边界至少为距离10,label离button右边界为距离为至少为10,imageView和label之间的距离为5,代码可以如下写:

      NSString *title = @"这是一个测试";

    [button setTitle:title forState:UIControlStateNormal];

    [button setImage:image forState:UIControlStateNormal];

      CGSize strSize = [title sizeWithFont:button.titleLabel.font];

      CGFloat totalLen = strSize.width + 5 + image.size.width;

      CGFloat edgeLen = (TAGS_BUTTON_WIDTH - totalLen) / 2;

      if (edgeLen < 10) {

          edgeLen = 10;

      }

    [button setImageEdgeInsets:UIEdgeInsetsMake(0, edgeLen, 0, edgeLen + 5)];

      [button setTitleEdgeInsets:UIEdgeInsetsMake(0, edgeLen + 50, edgeLen)];

       设置edgeInsets要始终记住的一个原则是:将label和imageView看成一个整体,imageView在前,label在后,中间没有空隙。。这段代码中,设置imageEdgeInsets时,imageView与左边距离为计算好的edgeLen,右边距是按照button的默认布局,label的右边与button右边的距离,就是label实际的右边应当与button右边的距离再向左移动5(实际中imageView与label有间距5,默认布局下可没有这个5,得把这个5让出来),就是edgeLen + 5。设置titleEdgeInset时,label与右边为计算好的edgeLen,想象imageView还在label的左边,与label没有空隙的话,那这个整体与左边的距离应该是多少呢?就是edgeLen+5,把间隙的5让出来嘛。

   我们再想一个稍复杂的情况:如果label在左,imageView在右,imageView在button上离右边界为固定值10,label离button左边界也为固定值10,应该怎么设呢?可以如下写代码:

      NSString *title = @"这是一个测试";

    [button setTitle:title forState:UIControlStateNormal];

    [button setImage:image forState:UIControlStateNormal];

      CGSize strSize = [title sizeWithFont:button.titleLabel.font];

      [button setImageEdgeInsets:UIEdgeInsetsMake(0BUTTON_WIDTH - 10 - image.size.width0, (10 - strSize.width))];    

      CGFloat titleRightInset = BUTTON_WIDTH - 10 - strSize.width;

      if (titleRightInset < 10 + image.size.width) {

          titleRightInset = 10 + image.size.width;

      }

      [button setTitleEdgeInsets:UIEdgeInsetsMake(0, (10 - image.size.width), 0, titleRightInset)];

      解释这段代码之前再强调一下UIButton控件的默认布局:imageView在左,label在右,中间没有空隙。imageView的左侧与button的左边界距离为button的width,去掉右侧留出的10,再去掉imageView的width,想像imageView后面还接着有一个label,那么label的右侧与button的右边界距离为10 - strSize.width,所以button的imageEdgeInsets属性就如上面代码的设置值了。再看label,它的右侧与button右边界的距离为button的width,去掉左侧留出的10,再去掉label的width,为保证label后面能放下一个图片,图片后面还有10的空白,故对titleRightInset做了如上的一些调整。想象label的左侧还有一个imageView,那么这个整体离button左边界的距离为10 - image.size.width。

    以上只考虑了width方向,height方向与width是独立的,比width更容易一些。

    设button的height:BUTTON_HEIGHT,如果imageView在上,与button上边界距离为10,label在下,与button下边界距离为10,可写如下代码。

      NSString *title = @"这是一个测试";

    [button setTitle:title forState:UIControlStateNormal];

    [button setImage:image forState:UIControlStateNormal];

      [button setImageEdgeInsets:UIEdgeInsetsMake(10, 0, BUTTON_HEIGHT - 10 - image.size.height , 0)];    

      [button setTitleEdgeInsets:UIEdgeInsetsMake(BUTTON_HEIGHT - 10 - button.titleLabel.frame.size.height, 0, 10, 0)];

   可以看到height方向上,imageView与label独立变化,不用考虑彼此。




最近又有新的发现发现 重写button的代理方法是最简单的方法  下面是自己的一些实验

//建议 继承UIButton并重写两个函数:

/*

-(CGRect) imageRectForContentRect:(CGRect)contentRect

-(CGRect) titleRectForContentRect:(CGRect)contentRect

简下面是自己对button类继承 (面向对象是菜菜菜鸟 所以设计的类不是很合理,求大神指点下)

头文件


typedef  NS_ENUM(NSInteger,UIButton_ImageTitleType)

{

    UIButton_ImageLeftTitleRight,

    UIButton_ImageRightTitleLeft,

    UIButton_ImageUpTitleDown,

    UIButton_ImageDownTitleUp

};

@interface ImageTitleButton : UIButton


@property (nonatomic,assign) UIButton_ImageTitleType imageTitleType;

@property (nonatomic,strong) UIImage *exampleImage;

@property (nonatomic,copy) NSString *exampleString;

@property (nonatomic,assign) CGFloat exampleFontSize;

@property (nonatomic,assign) CGFloat imageTitleSpace;


-(instancetype)initWithFrame:(CGRect)frame WithExampleImage:(UIImage *)exampleImage WithTitleString:(NSString *)exampleString WithExampleTitleFontSize:(CGFloat)exampleFontSize WithImageTitleSpace:(CGFloat)imageTitleSpace WithUIButton_ImageTitleType:(UIButton_ImageTitleType)imageTitleType;



实现文件

@implementation ImageTitleButton

{

    CGSize edgeImageSize;

    CGSize edgeTitleSize;

    CGFloat edgeLength;

}

//对属性并没有设置 只是根据样例去分配空间

-(instancetype)initWithFrame:(CGRect)frame WithExampleImage:(UIImage *)exampleImage WithTitleString:(NSString *)exampleString WithExampleTitleFontSize:(CGFloat)exampleFontSize WithImageTitleSpace:(CGFloat)imageTitleSpace WithUIButton_ImageTitleType:(UIButton_ImageTitleType)imageTitleType

{

    //WithExampleTitleFontSize:(CGFloat)exampleFontSize

    self = [super initWithFrame:frame];

    if (self)

    {

        _exampleImage = exampleImage;

        _exampleString = exampleString;

        _exampleFontSize = exampleFontSize;

        _imageTitleSpace = imageTitleSpace;

        _imageTitleType = imageTitleType;

        

        

        [self setTitle:exampleString forState:UIControlStateNormal];

        [self setImage:exampleImage forState:UIControlStateNormal];

        self.titleLabel.font = [UIFont systemFontOfSize:exampleFontSize];

        edgeImageSize = exampleImage.size;

        edgeTitleSize = [self calculateSizeWithStringLabel:self.titleLabel];

        if (_imageTitleType == UIButton_ImageDownTitleUp || _imageTitleType == UIButton_ImageUpTitleDown)//上下布局

        {

            edgeLength = (frame.size.height - edgeImageSize.height - _imageTitleSpace -edgeTitleSize.height)/2.0;

        }

        else//左右布局

        {

            edgeLength = (frame.size.width - edgeImageSize.width - _imageTitleSpace -edgeTitleSize.width)/2.0;

        }

    }

    return self;

}

//  [title boundingRectWithSize:<#(CGSize)#> options:<#(NSStringDrawingOptions)#> attributes:<#(NSDictionary *)#> context:<#(NSStringDrawingContext *)#>]  多行

//  [title sizeWithAttributes:@{NSFontAttributeName:button.titleLabel.font}]只能计算单行



-(CGSize )calculateSizeWithStringLabel:(UILabel *)label

{

    CGSize size;

    // 计算大小ios7以前的写法暂时还是能用的

    if ([label.text respondsToSelector:@selector(sizeWithFont:)])

    {

        size = [label.text sizeWithFont:label.font constrainedToSize:CGSizeMake(label.frame.size.width, MAXFLOAT) lineBreakMode:NSLineBreakByCharWrapping];

    }

    if ([label.text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)])

    {

        CGRect rectSize = [label.text boundingRectWithSize:CGSizeMake(label.frame.size.width, MAXFLOAT) options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:[NSDictionary dictionaryWithObject:label.font forKey:NSFontAttributeName] context:nil];

        size = rectSize.size;

    }

    return size;

    

}

//重写父类UIButton的方法


//更具buttonrect设定并返回文本labelrect

//contentRect是当前buttonframe

- (CGRect)titleRectForContentRect:(CGRect)contentRect


{

    

    NSLog(@"contentRect.size.width = %f",contentRect.size.width);

    CGFloat titleW = edgeTitleSize.width;

    CGFloat titleH = edgeTitleSize.height;

    CGFloat titleX;

    CGFloat titleY;


    if(_imageTitleType == UIButton_ImageDownTitleUp)//上字下图

    {

        titleX = (contentRect.size.width - titleW)/2.0;

        titleY = edgeLength;

    }

    else if (_imageTitleType == UIButton_ImageLeftTitleRight)//左图右字

    {

        titleX = (edgeLength + edgeImageSize.width +_imageTitleSpace);

        titleY = (contentRect.size.height - edgeTitleSize.height)/2.0;

    }

    else if(_imageTitleType == UIButton_ImageRightTitleLeft)//左字右图

    {

        titleX = (edgeLength);

        titleY = (contentRect.size.height - edgeTitleSize.height)/2.0;

    }

    else//上图下字

    {

        titleX = (contentRect.size.width - titleW)/2.0;

        titleY = (edgeImageSize.height + edgeLength + _imageTitleSpace);

    }

    contentRect = (CGRect){{titleX,titleY},{titleW,titleH}};


    return contentRect;

    

}


//更具buttonrect设定并返回UIImageViewrect


- (CGRect)imageRectForContentRect:(CGRect)contentRect


{

    CGFloat imageW = edgeImageSize.width;

    CGFloat imageH = edgeImageSize.height;

    CGFloat imageX;

    CGFloat imageY;


    

    if(_imageTitleType == UIButton_ImageDownTitleUp)//上字下图

    {

        imageX = (contentRect.size.width - imageW)/2.0;

        imageY = (edgeTitleSize.height + edgeLength +_imageTitleSpace);

    }

    else if (_imageTitleType == UIButton_ImageLeftTitleRight)//左图右字

    {

        imageX = edgeLength;

        imageY = (contentRect.size.height - edgeImageSize.height)/2.0;

    }

    else if(_imageTitleType == UIButton_ImageRightTitleLeft)//左字右图

    {

        imageX = edgeLength + edgeTitleSize.width + _imageTitleSpace;

        imageY = (contentRect.size.height - edgeImageSize.height)/2.0;

    }

    else//上图下字

    {

        imageX = (contentRect.size.width - imageW)/2.0;;

        imageY = edgeLength;

    }


    contentRect = (CGRect){{imageX,imageY},{imageW,imageH}};

    return contentRect;

    

}

//给用xib创建这个类对象时用的方法

-(id)initWithCoder:(NSCoder *)aDecoder

{

    if (self=[super initWithCoder:aDecoder]) {

    }

    return self;

}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值