iOS开发之UIButton的图片显示解惑

前言:

写这篇文章来给大家分享一下我了解的关于UIButton的图片显示知识点和我遇到的坑及解决方案,帮助遇到同样问题和相关知识点不清晰的同学,如有错误,欢迎指正,共同进步🤝。
本文在解析的时候可能较为啰嗦,是为了将思路完整呈现,对于初学者作用可能较大,老手可忽略,直接看结论。

需求:

相信大家都遇到过这种日常需求:一张图片上面有点击事件,同时这个控件的长宽比例固定或者干脆是个正方形,然而显示的图片则是长宽比例不固定的长方形,并且根据产品的需求,这张图片必须要覆盖整个控件,那么这图片势必要进行缩放;
还有图片必须不能变形(都知道,产品和UI的日常需求,变形了确实太丑),也就是说显示出来的时候原始图片长宽比例不能变。

分析:

涉及到图片缩放,那就不得不提UIViewcontentMode属性,既然要缩放并且图片长宽比例不能变,解决方案应该就是放大或缩小图片,但长宽比例不变,然后将图片居中显示,再裁减掉多余的部分,只显示控件大小的图片,当然是在clipToBoundsYES的情况下。

很显然,只有UIViewContentModeScaleAspectFill符合条件,这个枚举的作用大概是以下几种情况:

这里为了方便,假设横向长度为x,纵向高度为y

  1. 当目标控件和原始图片都为正方形时,只需要xy同比例缩放即可;

  2. 当原始图片xy比例不为1:1时,根据目标控件的xy比来适当的缩放:

    1)当原始图片的x:y >目标控件的x:y,缩放原始图片的y值等于目标控件的y值,然后根据原始图片的xy比缩放x,得到的图片肯定会在x方向大于目标控件,接着横向居中放置缩放后的原始图片,再裁掉多余部分。

    2)当原始图片的x:y <目标控件的x:y,缩放原始图片的x值等于目标控件的x值,然后根据原始图片的xy比缩放y,得到的图片肯定会在y方向大于目标控件,接着纵向居中放置缩放后的原始图片,再裁掉多余部分。

好了,这个枚举的作用介绍到这里,很清晰了(其他枚举的用法相信大家都知道,不知道的自行查资料,相信很容易找到)。

实验:

知道了这些知识点,要搞定这个需求就很容易了。
我先在这里准备了两张具有代表性的图片,模拟容易出错的情况。

  • 第一张,这张图非常小,是模拟加载比控件小的图时的情况:
    55x53.jpeg
  • 第二张,这张图是长方形,正中间有一轮明月,主要模拟长宽比例不一样时的情况,明月用来便于判断图片是否变形:
    525x350.jpeg

一、UIButton

我们写一个button,为了方便,长宽一样,设定为100,距离底部100,左右居中,然后clipToBounds属性为YES,为了便于分析,给个背景颜色,就用亮油油的火红火红的绿色,如图:

绿色的Button

开始设置图片

1) 先放一张长方形的图,来测试长宽比例不一样的情况,我这里用的是setImage:forState:(以下省去forState):

效果1
可以看到月亮已经扁了,明显变形,哦,知道,是因为contentMode的问题,设置一下
代码1
但是没有任何作用,就不上图了,运行后跟图效果1一模一样,怎么回事呢,经过查阅资料,我还是不知道🤓,总之就是UIButton.contentMode就像个摆设,而要设置button图片的contentMode只有用button.imageView.contentMode,我们来试试
代码2
效果2

好了,这样就对了,应该是满足我们刚才说的原始图片x:y > 目标控件x:y,于是y缩放到目标控件的y值大小,x等比例缩放,再居中显示,x方向两边多余的部分就被裁切了,好了,这种情况已经达到产品的需求。

2)刚才的情况测试了长方形且不比目标控件小的情况,另一种情况就比较烦了,也是这次我写这篇文章遇到的坑点,比目标控件小的图片,我们放上去试试,代码不变,contentMode还是scaleAspectFill:

效果3

😂此时我的心情跟效果3中那个小人的心情一模一样,还记得我们刚才设置的按钮绿色背景,现在起作用了,不然就只能看到很小的一个小人在中间。

为什么图片没有缩放呢,不是设置好了contentMode吗?这么坑的吗?呵呵,就是这么坑,这就是button的神奇之处,我想可能是因为是设置的是button的图标的原因吧(就是setImage这个方法)。

好,那我们试试setBackgoundImage,呵呵,算了,这样影响我排版了,先把setImage说完,因为我知道setBackgroundImage也没用,等会儿我们再完整地试试。

emmmm......怎么解决呢?经过查阅资料🌝,这次我找到了解决方案,原来UIControlcontentHorizontalAlignmentcontentVerticalAlignment两个属性

系统Api中ContentHorizontalAlignment
系统Api中ContentVerticalAlignment
我们这里显而易见是用fill了,试下效果:
代码4(就是没有代码3,要一一对应 🙂,下同)
效果4
代码5

效果5(1)

懵逼中......这跟说好的不一样啊,然后我点击了一下button,
效果5(2)

继续懵逼......不过效果总算符合预期了,这里究竟是怎么回事?

经过查阅资料,我猜应该是我在storyboard里面没有做设置,默认的是center,而我写成fill是在代码里写的,点击的时候才重新刷新了布局,如果直接在storyboard里面调整应该不会出现这种情况,不过到这里,应该知道要怎么设置了

storyboard中,如果用storyboard的可以直接选右边红框框出的选项

代码6

效果6

果然,小图也被放大了,并且没有变形,那就是裁去了多余的部分,总算搞定!至此,button设置图片的所有情况应该都涵盖了,正方形的情况是自然没问题的。

setBackgrounImage

好了,刚才我们说到的setBackgroundImage方法,试一下

代码7

这里因为我的小图准备的是一张近似正方形的图片,所以我把button改成100x200的长方形(之前一直是200x200),效果会更明显,如图
效果7(1)
效果7(2)

很明显,setBackgroundImage是将图片直接强行缩放到跟目标控件的大小一样,且任由图片变形,不会保持其长宽比例缩放后裁剪,同时各种设置完全没有作用,也就是没得商量🌚,完全不适合本文所提需求。

二、UIImageView

接下来尝试imageView,同样的,创建一个imageView,距离顶部100,长宽200,左右居中,clipToBoundsYES

代码
放长方形图
放小图

完美满足需求,此时imageView只需要再添加一个点击手势即可。

结论:

  1. UIButtonsetBackgroundImage方法不适合用此类目标控件与原始图片宽高比例不一致同时又要求显示出的图片不变形的需求,因为这个方法会无脑将原始图片生拉硬拽成目标控件的大小,即使原始图片各种变形。
  2. UIButtoncontentMode没有任何作用,设置了也没有效果,只有设置UIButtonimageViewcontentMode才有用,并且只有是调用的setImage时才有用。
  3. 由于UIButton继承自UIControl,UIControl有两个属性,contentHorizontalAlignmentcontentVerticalAlignment,这两个属性类似contentMode,是单独分别针对横向和竖向的,且默认都为center,猜测优先级上应该是这两个属性大于buttonimageViewcontentMode。所以如果buttonimageViewcontentMode和这两个属性矛盾,优先遵循UIControl的两个属性,即本文button用小图时所遇到的情况。
  4. 实现此需求的两个最佳解决方案:
    • UIButtonsetImage:forState:方法,设置UIButton.imageView.contentModeUIViewContentModeScaleAspectFill,同时设置contentHorizontalAlignmentcontentVerticalAlignment均为fill
    • UIImageView,设置contentModeUIViewContentModeScaleAspectFill,同时添加点击事件。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容