干货之UIButton的title和image自定义布局
当需要实现一个自定义布局图片和标题的按钮时候,不知道有多少少年直接布局了UIButton,亦或是自定义一个UIView,然后以空白UIButton、UILabel、UIImageVew作为subViews。
两者其实都一样,因为UIButton的内部subViews中,就已经存在一个UILabel和UIImageView。
不谈论优劣,只记录一下直接布局UIButton的过程。
因为UIButton已经有一个UILabel显示标题,一个ImageView显示图片,所以可以直接布局。但是需要注意下面记录的问题。
首先,对一个UIButton实例button直接设置title(使用setTitle或者setAttributedTitle方法)和image(使用setImage方法),会发现,图片和标题依次紧贴并排居中显示。
然后,修改一下这个button的titleLabel和imageView的frame,会发现,并没有什么作用。
最后,尝试使用方法setTitleEdgeInsets和setImageEdgeInsets,会发现,没有作用或者布局异常。
问题在于:
1.获取titleLabel的frame时候,size始终是(0, 0)
2.修改titleLabel的frame时机不对
将上述修改操作放在方法layoutSubviews中是合适的。
至于创建UIButton的子类重载方法,还是创建分类来swizzle方法都可以。
即使在这个时机,使用setTitleEdgeInsets还是可能会出现文字显示不全的问题。建议直接修改titleLabel的frame。
我采用了创建分类的方案。定义了一个方法,在+load方法中与layoutSubViews交换。
- - (void)base_layoutSubviews
- {
- [self base_layoutSubviews];
- if (self.resetTitleAndImageLayoutBlock) {
- self.resetTitleAndImageLayoutBlock();
- }
- }
代码中自定义的block变量,将重置布局代码延迟到此处调用。
以下代码,是我写的UIButton分类中自定义图片和标题布局的主要方法,其中图片位置暂时只自定义了四种:
- - (void)resetButtonTitleAndImageLayoutWithMidInset:(CGFloat)midInset imageLocation:(ButtonImageLocation)imageLocation
- {
- CGSize titleSize = [self.titleLabel.attributedText boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;;
- CGSize imageSize = self.imageView.size;
- __weak typeof(self) weakSelf = self;
- //因为UIButton在layoutSubviews时候,会重置titleLabel的frame,所以需要延迟调用block
- self.resetTitleAndImageLayoutBlock = ^{
- switch (imageLocation) {
- case ButtonImageLocationUp: {
- CGFloat imageOriginX = (weakSelf.width - imageSize.width) / 2.0;
- CGFloat imageOriginY = (weakSelf.height - titleSize.height - midInset - imageSize.height) / 2.0;
- weakSelf.imageEdgeInsets = UIEdgeInsetsMake(imageOriginY, imageOriginX, weakSelf.height - imageOriginY - imageSize.height, imageOriginX);
- CGFloat titleOriginX = (weakSelf.width - titleSize.width) / 2.0;
- CGFloat titleOriginY = imageOriginY + imageSize.height + midInset;
- weakSelf.titleEdgeInsets = UIEdgeInsetsMake(titleOriginY, titleOriginX, weakSelf.height - titleOriginY - titleSize.height, titleOriginX);
- break;
- }
- case ButtonImageLocationLeft: {
- CGFloat imageOriginX = (weakSelf.width - imageSize.width - midInset - titleSize.width) / 2.0;
- CGFloat imageOriginY = (weakSelf.height - imageSize.height) / 2.0;
- weakSelf.imageEdgeInsets = UIEdgeInsetsMake(imageOriginY, imageOriginX, imageOriginY, weakSelf.width - imageOriginX - imageSize.width);
- CGFloat titleOriginX = imageOriginX + imageSize.width + midInset;
- //横向时候,label的frame可以取较大范围
- // CGFloat titleOriginY = (weakSelf.height - titleSize.height) / 2.0;
- // weakSelf.titleLabel.frame = CGRectMake(titleOriginX, titleOriginY, titleSize.width, titleSize.height);
- weakSelf.titleLabel.frame = CGRectMake(titleOriginX, , weakSelf.width - titleOriginX, weakSelf.height);
- [weakSelf.titleLabel setTextAlignment:NSTextAlignmentLeft];
- break;
- }
- case ButtonImageLocationDown: {
- CGFloat titleOriginX = (weakSelf.width - titleSize.width) / 2.0;
- CGFloat titleOriginY = (weakSelf.height - titleSize.height - midInset - imageSize.height) / 2.0;
- weakSelf.titleEdgeInsets = UIEdgeInsetsMake(titleOriginY, titleOriginX, weakSelf.height - titleOriginY - titleSize.height, titleOriginX);
- CGFloat imageOriginX = (weakSelf.width - imageSize.width) / 2.0;
- CGFloat imageOriginY = titleOriginY + titleSize.height + midInset;
- weakSelf.imageEdgeInsets = UIEdgeInsetsMake(imageOriginY, imageOriginX, weakSelf.height - imageOriginY - imageSize.height, imageOriginX);
- break;
- }
- case ButtonImageLocationRight: {
- CGFloat titleOriginX = (weakSelf.width - imageSize.width - midInset - titleSize.width) / 2.0;
- //横向时候,label的frame可以取较大范围
- // CGFloat titleOriginY = (weakSelf.height - titleSize.height) / 2.0;
- // weakSelf.titleLabel.frame = CGRectMake(titleOriginX, titleOriginY, titleSize.width, titleSize.height);
- weakSelf.titleLabel.frame = CGRectMake(, , titleOriginX + titleSize.width, weakSelf.height);
- [weakSelf.titleLabel setTextAlignment:NSTextAlignmentRight];
- CGFloat imageOriginX = titleOriginX + titleSize.width + midInset;
- CGFloat imageOriginY = (weakSelf.height - imageSize.height) / 2.0;
- weakSelf.imageEdgeInsets = UIEdgeInsetsMake(imageOriginY, imageOriginX, imageOriginY, weakSelf.width - imageOriginX - imageSize.width);
- break;
- }
- }
- };
- }
完整的代码请参考Base项目中UIButton的分类。
Base项目已更新:https://github.com/ALongWay/base.git
干货之UIButton的title和image自定义布局的更多相关文章
- UIButton内部子控件自定义布局-“UIEdgeInsets”
UIButton UIButton做frame动画时,不响应点击 在一个View内部加入几个按钮,然后改变这个view的frame来做动画,但是按钮不响应点击事件. 问题代码 __block CGRe ...
- iOS 11 导航栏 item 偏移问题 和 Swift 下 UIButton 设置 title、image 显示问题
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...
- UIButton的文本与图片的布局
UIButton内部文本和图片的布局是我们日常代码中,不可缺少的部分,按钮默认左边图片右边文本,那要实现左边文本,右边图片,我们该怎么解决呢,上面图片,下面文本又该怎么办呢 其实很简单,今天总结下,目 ...
- 5分钟 搞定UIButton的文本与图片的布局
UIButton内部文本和图片的布局是我们日常代码中,不可缺少的部分,按钮默认左边图片右边文本,那要实现左边文本,右边图片,我们该怎么解决呢,上面图片,下面文本又该怎么办呢 其实很简单,今天总结下,目 ...
- 【Android基础】listview控件的使用(4)-----自定义布局的listview的使用
前面我介绍了listview控件的不同用法,但是这些用法在实际的开发项目中是不足以满足需求的,因为前面的几种用法只能简单的显示文本信息,而且布局都比较单一,很难做出复杂的结果,在实际的开发项目中,90 ...
- 利用修改div的位置+js对象存储div信息 实现简单的div自定义布局功能
原文:利用修改div的位置+js对象存储div信息 实现简单的div自定义布局功能 利用修改div的位置+js对象存储div信息 实现简单的div自定义布局功能1.在界面上添加几个checkbox和一 ...
- Android开发学习之路--UI之自定义布局和控件
新的一年已经开始了,今天已经是初二了,两天没有学习了,还是要来继续学习下.一般手机的title都是actionbar,就像iphone一样可以后退,可以编辑.这里自定义布局就来实现下这个功能,首先准备 ...
- 【转】Android AlertDialog自定义布局
原文网址:https://blog.csdn.net/u010694658/article/details/53022294 由于开发中经常使用弹框,然而系统自带的弹框太局限,也不太美观,经常不能满足 ...
- form-create教程:自定义布局,实现一行多个组件
本文将介绍form-create如何自定义布局,实现一行多个组件 form-create 是一个可以通过 JSON 生成具有动态渲染.数据收集.验证和提交功能的表单生成器.并且支持生成任何 Vue 组 ...
随机推荐
- GoodReader跨域访问HT for Web手册
最近下载了GoodReader App,发现GoodReader中打开的页面不仅支持WebGL,同时还允许跨域访问资源,以前不少HT for Web手册的例子需要Web服务器发布的方式才能访问,否则需 ...
- 理解SQL Server是如何执行查询的 (2/3)
查询执行的内存授予(Query Execution Memory Grant) 有些操作符需要较多的内存才能完成操作.例如,SORT.HASH.HAS聚合等.执行计划通过操作符需要处理数据量的预估值( ...
- html5的canvas绘制迷宫地图
canvas标签一直是html5的亮点,用它可以实现很多东西.我想用它来绘画像迷宫那样的地图.借助到的工具有瓦片地图编辑器tiled(点击跳转到下载链接). 如图:如果你想要画像这样的迷宫地图,如果不 ...
- WinPhone学习笔记(一)——页面导航与页面相关
最近学一下Windows Phone(接下来简称“WinPhone”)的开发,在很久很久前稍探究一下WinPhone中对一些传感器的开发,那么现在就从头来学学WinPhone的开发.先从WinPhon ...
- 三星S4,呼转的来电,在来电界面上不显示的解决方案
因为工作关系,我有2个号码是呼叫转移到我现在的手机上的,如果有呼叫转移的来电的话,在通话界面里面没有提示该来电是呼叫转移来的.之前我用的诺基亚的,可以看到呼叫转移的来电,在号码的左边有个拐弯的箭头,提 ...
- Using Stored Programs with MySQLdb
http://flylib.com/books/en/1.142.1.125/1/ Using Stored Programs with MySQLdb The techniques for call ...
- Map遍历两种方式
Java代码 Map<String,String> map=new HashMap<String,String>(); map.put("username" ...
- maven url
aliyun阿里云Maven仓库地址--加速你的maven构建 maven仓库用过的人都知道,国内有多么的悲催.还好有比较好用的镜像可以使用,尽快记录下来.速度提升100倍. http://mav ...
- jenkins 邮件配置
jenkins 自带一个邮件的通知的功能,但是自带的邮件通知功能,有点简单不能自定义信息,所以我们安装邮件插件Email-ext plugin.1.首先在系统管理-插件管理-安装Email-ext p ...
- jshint配置(js检查)
JSHint的选项配置 asi 如果是真,JSHint会无视没有加分号的行尾,自动补全分号一直是Javascript很有争议的一个语法特性.默认,JSHint会要求你在每个语句后面加上分号,但是如果你 ...