UIEdgeInsetsMake使用详解

作者: MrFire_ | 来源:发表于2016-04-08 18:02 被阅读19030次
    • 示例
      在创建button的时候经常需要在button上添加图片和按钮,而且一般情况下我们需要的都是图片在上、标题在下的效果(灰色的为button):
    屏幕快照 2016-04-08 下午4.38.33.png

    而当我们设置好title和image后发现是图片居左,标题居右的:

    屏幕快照 2016-04-08 下午4.40.19.png

    当然这不是我们想要的效果,于是通过设置UIEdgeInsetsMake属性来达到我们想要的效果,但具体是要设置多少,每次做的时候我总是在尝试,一点一点的去试,直达到想要的效果,这样做事非常让人头疼的,而且对原理什么的完全不清楚,更让人头疼的是万一修改需求,例如字体的多少或者大小发生了变化,那么又要一顿狂试,疯了的感觉,有木有!于是有一天(也就是今天)我终于受不了了,开始研究UIEdgeInsetsMake到底是个什么鬼东西。


    • 先看定义
    typedef struct UIEdgeInsets {
        CGFloat top, left, bottom, right;  // specify amount to inset (positive) for each of the edges. values can be negative to 'outset'
    } UIEdgeInsets;
    

    UIEdgeInsets实际就是一个结构体(之前在这写的是枚举,感谢无刃之刃提出的错误),UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)要设置的就是四个边距,先看一张图:

    image_2.png

    图中,蓝色标识为可变区域, 绿色标识为不变区域。UIEdgeInsets结构体的属性topbottom为一对,用来指定纵向可变区域(黑色虚线矩形),leftright为一对,用来指定横向可变区域(白色虚线矩形)。当UIButton/UIImageView的size大于UIImage的size时,会调整图片中可变区域大小以铺满整个控件,具体调整规则如下:
    (1)控件宽度大于图片宽度,拉伸白色虚线矩形
    (2)控件高度大于图片高度,拉伸黑色虚线矩形
    (3)控制宽度小于图片宽度时,横向整体缩小(可变区与不变区比例不变)
    (4)控制高度小于图片高度时,纵向整体缩小(可变区与不变区比例不变)

    上面的图片和解释来自于一叶博客,按照我的理解可以这样解释:top就是距离顶部的距离在默认的基础上又加上设置的距离,拿开头的button来说,在button仅设置image的时候(如果同时设置了image和title效果又是不一样的,下面会详解,稍安勿躁),image默认是居中的,相当于进行了这样的设置:

    [button setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
    

    如果我们在这个时候设置了:

    [button setImageEdgeInsets:UIEdgeInsetsMake(20, 0, 0, 0)];
    

    就相当于在图片居中的基础上,将图片又下移了20,如果是-20则是在原有的基础上向上移20,其他几个参数同理,正数就是距相应的边的距离增加,负数就是距相应的距离减少。关于这一点大家若想真正弄清楚,单纯的去看我写的或者其他任何一个人写的文章搜几乎是不可能的,最好的办法就是去实践,自己动手写一段代码,一个变量一个变量的去试验,每改变一个变量的值会出现什么样的效果,这样才能理解的更加透彻。在这之前我在网上搜了很多这方面的资料,大都是一个人写的,被别人拿去粘贴复制,千篇一律,或许不是别人讲的不透彻,只是自己缺少实践而已。扯远了,回到主题,接下来说一下同时设置图片和标题的情况:

    • 为button同时设置图片和标题
      文章开头就说了,当我们给button设置图片和title的时候默认是图片居左,标题距右并排排列的:
        [button setImage:[UIImage imageNamed:@"ffw_32"] forState:UIControlStateNormal];
        [button setTitle:@"按钮" forState:UIControlStateNormal];
    

    我们回到文章开头的第二章图片,发生这样变化的根源是什么呢?那就是当我们同时添加图片和标题时,图片默认会向左偏移button的titleLabel的宽度,而标题会向右偏移图片的宽度,既然如此,我们就可以设置偏移量来达到我们想要的任何效果,一步一步来,先居中(大家可以先想一下这几个参数应该怎么设置):

        [button setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, -button.titleLabel.intrinsicContentSize.width)];
        [button setTitleEdgeInsets:UIEdgeInsetsMake(0, -button.currentImage.size.width, 0, 0)];
    

    效果:

    屏幕快照 2016-04-08 下午5.45.58.png
    大家可能注意到了我设置image偏移量的时候并不是设置的-button.titleLabel.bounds.size.width,而是-button.titleLabel.intrinsicContentSize.width,因为在iOS8之后-button.titleLabel.bounds.size.width的值为0,经多方搜索才找到一个替代的方法,这样设置的意义就是将image的偏移量距右边的距离减少了titleLabel的宽度,由于默认是向左便宜了这么多,我们这样设置之后相当于抵消了左移的偏移量,所以图片就居中了,对于title道理是一样的。这一点明白之后剩下的就没什么难题了,继续,title下移,image上移:
        [button setImageEdgeInsets:UIEdgeInsetsMake(-button.titleLabel.intrinsicContentSize.height, 0, 0, -button.titleLabel.intrinsicContentSize.width)];
        [button setTitleEdgeInsets:UIEdgeInsetsMake(button.currentImage.size.height, -button.currentImage.size.width, 0, 0)];
    

    效果:

    屏幕快照 2016-04-08 下午5.55.24.png

    图片和标题好像有点近,好办,再加一点:

    [button setTitleEdgeInsets:UIEdgeInsetsMake(button.currentImage.size.height + 20, -button.currentImage.size.width, 0, 0)];
    

    分开了:

    屏幕快照 2016-04-08 下午5.57.56.png

    附上我的测试demo,有需要的可以直接修改参数:

        UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 160, 160)];
        [button setImage:[UIImage imageNamed:@"ffw_32"] forState:UIControlStateNormal];
        [button setTitle:@"按钮" forState:UIControlStateNormal];
        button.titleLabel.font = [UIFont systemFontOfSize:14];
        [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        button.center = self.view.center;
        button.backgroundColor = [UIColor grayColor];
        [self.view addSubview:button];
        NSLog(@"%f",-button.titleLabel.bounds.size.width);
        
        [button setImageEdgeInsets:UIEdgeInsetsMake(-button.titleLabel.intrinsicContentSize.height, 0, 0, -button.titleLabel.intrinsicContentSize.width)];
        [button setTitleEdgeInsets:UIEdgeInsetsMake(button.currentImage.size.height + 20, -button.currentImage.size.width, 0, 0)];
    
    • 后记
      作为iOS新人,我在找这方面的资料时着实费了不少劲,希望这篇文章能帮助同我一样迷茫的盆友,另外非常感谢一叶博客Learning Notes的文章,受益匪浅!


    • End

    相关文章

      网友评论

      • Janine_:感谢作者,之前我都是直接用sdlayout来布局,现在不想用第三方了,研究了半天,多亏作者,省了我很多时间:+1:
      • RBNote:`于是有一天(也就是今天)我终于受不了了,开始研究UIEdgeInsetsMake到底是个什么鬼东西。` 同感。
      • BeethOven:文章中“发生这样变化的根源是什么呢?那就是当我们同时添加图片和标题时,图片默认会向左偏移button的titleLabel的宽度,而标题会向右偏移图片的宽度” ,文字和图片是怎么实现无间隙的。假设按钮宽50,imageView宽40,titleLabel宽10,imageView默认向左偏移10,x 不应该从原来的5变成-5嘛? 实际却不是如此?是我哪儿理解错了嘛
        滚来滚去的桔子:是在原来的偏移量上再偏移。
      • 一个不太努力的代码搬运工:楼主写的很好,比那些随便复制粘贴的要好,intrinsicContentSize尤其是这个属性,我在实验的时候也是发现titleLabel的size为0,在楼主这里找到解决方法,感谢!
        MrFire_:@losedMemory 能帮到你就好:smile:
      • 060ab1545c5d:写的非常清楚明白。以前也找过很多东西,但是感觉就是看不太懂。你这篇文章完全解决了我的问题。谢谢楼主。大力支持
        MrFire_:@心无旁骛_bb84 谢谢?
      • 47e2b53b72da:深度好文!
      • Lee_Jimmy:楼主是不是把 纵向的(白色区域) 和 横向的(黑色区域) 写反了?
      • H_Cynic:- (instancetype)init {
        self = [super init];
        if (self) {
        self.imageView.contentMode = UIViewContentModeCenter;
        self.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
        self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
        }
        return self;
        }

        - (void)layoutSubviews {
        [super layoutSubviews];
        self.imageView.frame = CGRectMake(0, 0, self.w * 2 / 3, self.h * 2 / 3);
        self.imageView.contentMode = UIViewContentModeCenter;
        self.imageView.centerX = self.w / 2.0;
        self.titleLabel.frame = CGRectMake(0, self.imageView.bottom, self.w, self.h - self.imageView.h);
        self.titleLabel.textAlignment = NSTextAlignmentCenter;
        }
        希望对你有帮助吧
      • 小码儿:继续努力啊
      • 扣肉快快跑:帮助很大, 谢谢分享
      • 3109bf108044:想问下作者,比如默认情况button的图片默认会向左偏移button的titleLabel的宽度,让图片居中[button setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, -button.titleLabel.intrinsicContentSize.width)],这样就可以了,相当于让图片向右移动titleLabel的宽度等于抵消了图片默认会向左偏移button的titleLabel的宽度。
        typedef struct UIEdgeInsets {
        CGFloat top, left, bottom, right; // specify amount to inset (positive) for each of the edges. values can be negative to 'outset'
        } UIEdgeInsets;
        有一点我不明白,为何默认向左偏移了需要设置向右的才能抵消,为何不能这样,比如:默认(0,20,0,0)改成(0,-20,0,0),这样抵消不可以吗?
      • 高猛:赞一个
      • 37c7796cd658:写的很棒 自己开发了 两个应用但是也不是很明白该怎么设置UIEdgeInsetsMake这个参数,受教了,谢谢
      • wg689:自定义按钮,父类重写layout sub view
        想怎么摆就怎么摆
      • YxYYxY:您好!我想请教一个问题,您在文中说到的同时设置图片和文字的时候,“图片默认会向左偏移button的titleLabel的宽度”,而做法是[button setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, -button.titleLabel.intrinsicContentSize.width)];将图片向右的距离减少一个label的宽度,但是我自己测试的时候我想的是既然可以把右边的减少,那我把左边增加一个label的宽度,应该也是同样的效果,但是实验结果好像并不是那样,偏移的距离并达不到一个lable的宽度,请问一下这是什么原因呢?谢谢
        YxYYxY:@hungryBoy :cry:我研究了半天,也没想通原因,希望能你能研究出答案分享一下!
        MrFire_:@YxYYxY 这个我还没试过,我们可以共同研究一下
      • JsJavaCoder:当然这不是我们想要的效果,于是通过设置UIEdgeInsetsMake属性来达到我们想要的效果,但具体是要设置多少,每次做的时候我总是在尝试,一点一点的去试,直达到想要的效果,这样做事非常让人头疼的,而且对原理什么的完全不清楚,更让人头疼的是万一修改需求,例如字体的多少或者大小发生了变化,那么又要一顿狂试,疯了的感觉,有木有!于是有一天(也就是今天)我终于受不了了,开始研究UIEdgeInsetsMake到底是个什么鬼东西。!!!!!!!!!!!!!!!!!!和你一样哈哈哈哈
        MrFire_:@猪猪和大大 彼此彼此,哈哈…
      • 琴月阳:实践结果告诉我,偏移量是UIEdgeInsets里设置的1/2,比如(0,-64,0,0),实际上只向左偏移了32个像素,想不通了
        陶小亮:@琴月阳 什么叫缩图的原因啊?
        陶小亮:@琴月阳 没懂,
        琴月阳:原来是因为缩图的原因:joy:
      • GTMYang:非常有用
      • lesmiserables0:不错不错,赞一个~!
      • 阿召:[button setImageEdgeInsets:UIEdgeInsetsMake(20, 0, 0, 0)];这句话是向下偏移10不是20哦
        MrFire_:@真是艹0 现在还有问题吗?我最近比较忙,没来得及回复,还望见谅
        3a169b0787bc:@hungryBoy 请问为什么 是10而不是20?
        MrFire_:@阿召 谢谢!
      • 云画的跃光:你好,我想请教你一个问题,view1的宽高是300
        [view2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(view1).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));

        }];
        为什么view2的宽高变成了280啊?
        MrFire_:@馒头小爱 估计现在应该睡醒了
        云画的跃光:@hungryBoy 嘻嘻,没睡醒,没反应过来,只算了一边剪去的距离
        MrFire_:@馒头小爱 你去查一下UIEdgeInsetsMake的用法,看后就知道了,四个方向都减少了10,不是280应该是多少呢?
      • 郑明明:不错哈
        MrFire_: @nineteen__ 谢谢
      • sinno:"相当于在图片居中的基础上,将图片又上移了20,如果是-20则是在原有的基础上向下移20"
        正数应该是将图片下移了吧~ 负数是上移 。。。
        MrFire_:@sinno 是的,已改正,谢谢!

      本文标题:UIEdgeInsetsMake使用详解

      本文链接:https://www.haomeiwen.com/subject/ypmvlttx.html