内容字号:默认大号超大号

段落设置:段首缩进取消段首缩进

字体设置:切换到微软雅黑切换到宋体

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

2018-11-07 18:02 出处:清屏网 人气: 评论(0

前言:

写这篇文章来给大家分享一下我了解的关于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

:joy:此时我的心情跟效果3中那个小人的心情一模一样,还记得我们刚才设置的按钮绿色背景,现在起作用了,不然就只能看到很小的一个小人在中间。为什么图片没有缩放呢,不是设置好了 contentMode 吗?这么坑的吗?呵呵,就是这么坑,这就是 button 的神奇之处,我想可能是因为是设置的是button的图标的原因吧(就是 setImage 这个方法)。好,那我们试试 setBackgoundImage ,呵呵,算了,这样影响我排版了,先把 setImage 说完,因为我知道 setBackgroundImage 也没用,等会儿我们再完整地试试。

emmmm......怎么解决呢?经过查阅资料:full_moon_with_face:,这次我找到了解决方案,原来 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 ,所以如果 imageViewcontentMode 和这两个属性矛盾,优先遵循这两个属性,即本文 button 用小图时所遇到的情况。

  4. 实现此需求的两个最佳解决方案:

    • UIButtonsetImage:forState: 方法,设置 UIButton.imageView.contentModeUIViewContentModeScaleAspectFill ,同时设置 contentHorizontalAlignmentcontentVerticalAlignment 均为 fill

    • UIImageView ,设置 contentModeUIViewContentModeScaleAspectFill ,同时添加点击事件。

分享给小伙伴们:
本文标签: UIButtoniOS开发

相关文章

发表评论愿您的每句评论,都能给大家的生活添色彩,带来共鸣,带来思索,带来快乐。

CopyRight © 2015-2016 QingPingShan.com , All Rights Reserved.

清屏网 版权所有 豫ICP备15026204号