关于UIButton的图文混排之图片

    xiaoxiao2022-06-23  37

    一,概述

        UIButton在日常开发中经常用到UI控件,它是继承自UIControl,并且集成UIImageview和UIlabel封装而成的 日常开发中我们经常需要做一些定制,这些定制很简单,就是改变image和title的位置而已.

    二,涉及的相关属性

    * UIButton的属性

    @property(nonatomic) UIEdgeInsets contentEdgeInsets UI_APPEARANCE_SELECTOR(UI_APPEARANCE_SELECTOR 表示可以外观定制); @property(nonatomic) UIEdgeInsets titleEdgeInsets; @property(nonatomic) UIEdgeInsets imageEdgeInsets;

    * UIControl的属性

    @property(nonatomic) UIControlContentVerticalAlignment contentVerticalAlignment; @property(nonatomic) UIControlContentHorizontalAlignment contentHorizontalAlignment;

    三,相关的简单测试

    UIButton * abutton =({ UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame =CGRectMake(0, 0, 200, 200); button.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/2); [button setTitle:@"我好怕怕!" forState:UIControlStateNormal]; [button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; [button setImage:[UIImage imageNamed:@"small"] forState:UIControlStateNormal]; [button setBackgroundColor:[UIColor orangeColor]]; button; }); [self.view addSubview:abutton]; //测试 //button 内部imageView的frame NSLog(@"%@",NSStringFromCGRect(abutton.imageView.frame)); //button 内部label 的frame NSLog(@"%@",NSStringFromCGRect(abutton.titleLabel.frame));

    1>仅有文字

         

    打印结果:

    2016-09-14 10:56:06.213 撒打发士大夫撒旦法[2948:48347] {{0, 0}, {0, 0}}

    2016-09-14 10:56:06.213 撒打发士大夫撒旦法[2948:48347] {{61.333333333333336, 89.333333333333329}, {77.333333333333329, 21.666666666666668}}

    分析结果:

          控件本身的大小是(200,200),此时label的大小是{77.333333333333329, 21.666666666666668} 位置为居中.

    2>仅有图片

       

    打印结果:

    2016-09-14 10:59:47.868撒打发士大夫撒旦法[3140:52538] {{72, 71}, {56, 58}}

    2016-09-14 10:59:47.870撒打发士大夫撒旦法[3140:52538] {{0, 0}, {0, 0}}

    分析结果 :

      此时控件本身的大小是(200,200),此时imageView的大小是{56, 58} 位置居中.  而此时我们查看图片的尺寸大小,它的大小也是{56,58}

      这样似乎看来,button控件内部对ImageView的设置是以图片本身尺寸的大小进行创建的.

    3>文字和图片共存

         1> 图片尺寸小于(200 ,200)

             

    打印结果:

    2016-09-14 11:12:21.496 撒打发士大夫撒旦法[3543:59053] {{33.333333333333336, 71}, {56, 58}}

    2016-09-14 11:12:21.496 撒打发士大夫撒旦法[3543:59053] {{89.333333333333343, 89.333333333333329}, {77.333333333333329, 21.666666666666668}}

        2>图片尺寸大于(200,200)

             

    打印结果:

    2016-09-14 11:14:29.573撒打发士大夫撒旦法[3608:60400] {{0, 0}, {200, 200}}

    2016-09-14 11:14:29.573撒打发士大夫撒旦法[3608:60400] {{200, 89.333333333333329}, {0, 21.666666666666668}}

    分析结果:

      当文字和图片同时存在是,当图片本身的尺寸大于button控件的尺寸时,即使设置了文字,仍然只显示图片,不显示文字. 并且图片做伸缩处理铺满整个控件.

    四, 相关问题总结

      1> 关于Button图片自适应和文本自适应问题

           *图片自适应*

             我们在上面的测试中,发现当我们的图片尺寸小于button控件本身的尺寸时, 图片是以图片的尺寸来创建ImageView的,且居中显示. 如果我们想让小图片铺满整个Button控件怎么办呢? 

            * 不成功方法:

             1)用ImageView本身自适应的方法可行吗?  显然不行,因为ImageView的大小本身就是依据图片的尺寸进行创建的, 所以当然没有效果.

             2)用Button自身的ContentMode设置,也是没效果的.

           * 成功的方法:          1) 

    button.contentHorizontalAlignment= UIControlContentHorizontalAlignmentFill; button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;

             2)继承UIButton,重写 imageRectForContentRect 方法返回button的bounds  

    - (CGRect)imageRectForContentRect:(CGRect)bounds{ return CGRectMake(0.0, 0.0, self.size.width, self.size.height); }

          *文本自适应*

               同理图片,titleLabel的大小,是根据传入的文字来进行计算创建的, 那么当文字的宽度高于控件的宽度怎么办呢?

             * 不成功的方法

               1)用titleLabel自身的sizeToFit来自适应可行吗?显然也是不行的,因为titleLabel的大小就是根据文字来创建的,所以当然没有效果.

             * 成功的方法

               1)使用Button的sizeToFit 方法, 不过button的本身的形状会变形, 假如不影响你的需求可以尝试.

               2)使用titleLabel的

    numberOfLines的自动换行.

               3)使用titleLabel的

    adjustsFontSizeToFitWidth的方法, 不过titlLabel的字体会变小,来适应UIButton,假如不影响需求可以尝试.

        2>UIButton上的imageEdgeInsets,titleEdgeInsets与contentEdgeInsets的属性使用

            相关含义:

                   imageEdgeInsets  设置UIButton的实例变量的图片位于四个边框的间的间距(这里边框,是指图片本身的初始状态来作参考的)

                   titleEdgeInsets      设置UIButton的实例变量的标题位于四个边框的间的间距(这里边框,是指标题本身的初始状态来作参考的)

                 contentEdgeInsets  UIButton中包含的所有内容与它本身的frame间的边距

           举个例子:

                初始状态:

    UIButton * abutton =({ UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame =CGRectMake(0, 0, 200, 200); button.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/2); [button setTitle:@"我好怕怕!" forState:UIControlStateNormal]; [button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; [button setImage:[UIImage imageNamed:@"small"] forState:UIControlStateNormal]; [button setBackgroundColor:[UIColor orangeColor]]; button.titleLabel.adjustsFontSizeToFitWidth =YES; button; }); [self.view addSubview:abutton];

     效果图:

       

    改变状态

    UIButton * abutton =({ UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame =CGRectMake(0, 0, 200, 200); button.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/2); [button setTitle:@"我好怕怕!" forState:UIControlStateNormal]; [button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; [button setImage:[UIImage imageNamed:@"small"] forState:UIControlStateNormal]; button.titleEdgeInsets=UIEdgeInsetsMake(0,-button.imageView.bounds.size.width, 0, button.imageView.bounds.size.width); button.imageEdgeInsets =UIEdgeInsetsMake(0,button.titleLabel.bounds.size.width, 0, -button.titleLabel.bounds.size.width); [button setBackgroundColor:[UIColor orangeColor]]; button.titleLabel.adjustsFontSizeToFitWidth =YES; button; }); [self.view addSubview:abutton];

    效果图:

      

    怎么理解呢? 

         button.titleEdgeInsets=UIEdgeInsetsMake(0,-button.imageView.bounds.size.width0, button.imageView.bounds.size.width);

         button.imageEdgeInsets =UIEdgeInsetsMake(0,button.titleLabel.bounds.size.width0, -button.titleLabel.bounds.size.width);

    titleLabel左边相对于原来的位置向左移动了ImageView的宽度(-)

    titleLabel右边相对于原来的位置向左移动了ImageView的宽度(+)

    同是向左移动为什么左边是"-"的,而右边的是"+"的呢? 这是因为UIEdgeInset本身就是相对于内部边界而言的,左边相对于原来的位置已经超出了内部边界, 而右边向左却仍然在内部边界之内.

          3>关于contentVerticalAlignment 和 contentHorizontalAlignment;

             contentVerticalAlignment和contentHorizontalAlignment 是UIControl的两个属性,用于排列内部元素. typedef NS_ENUM(NSInteger, UIControlContentVerticalAlignment) { UIControlContentVerticalAlignmentCenter = 0, UIControlContentVerticalAlignmentTop = 1, UIControlContentVerticalAlignmentBottom = 2, UIControlContentVerticalAlignmentFill = 3, }; typedef NS_ENUM(NSInteger, UIControlContentHorizontalAlignment) { UIControlContentHorizontalAlignmentCenter = 0, UIControlContentHorizontalAlignmentLeft = 1, UIControlContentHorizontalAlignmentRight = 2, UIControlContentHorizontalAlignmentFill = 3, };共有16种选择, 其中默认的是居中选择 列举其它的部分选择方式

    注意:       在V:fill H:fill 选择中,title并没有在水平方向铺满全屏,仍然保持titleLab的原始宽度. 这说明TitleLabel的宽度,不能被拉伸,却能被压缩. 

    转载请注明原文地址: https://ju.6miu.com/read-1123550.html

    最新回复(0)