当需要实现一个自定义布局图片和标题的按钮时候,不知道有多少少年直接布局了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自定义布局的更多相关文章

  1. UIButton内部子控件自定义布局-“UIEdgeInsets”

    UIButton UIButton做frame动画时,不响应点击 在一个View内部加入几个按钮,然后改变这个view的frame来做动画,但是按钮不响应点击事件. 问题代码 __block CGRe ...

  2. 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 ...

  3. UIButton的文本与图片的布局

    UIButton内部文本和图片的布局是我们日常代码中,不可缺少的部分,按钮默认左边图片右边文本,那要实现左边文本,右边图片,我们该怎么解决呢,上面图片,下面文本又该怎么办呢 其实很简单,今天总结下,目 ...

  4. 5分钟 搞定UIButton的文本与图片的布局

    UIButton内部文本和图片的布局是我们日常代码中,不可缺少的部分,按钮默认左边图片右边文本,那要实现左边文本,右边图片,我们该怎么解决呢,上面图片,下面文本又该怎么办呢 其实很简单,今天总结下,目 ...

  5. 【Android基础】listview控件的使用(4)-----自定义布局的listview的使用

    前面我介绍了listview控件的不同用法,但是这些用法在实际的开发项目中是不足以满足需求的,因为前面的几种用法只能简单的显示文本信息,而且布局都比较单一,很难做出复杂的结果,在实际的开发项目中,90 ...

  6. 利用修改div的位置+js对象存储div信息 实现简单的div自定义布局功能

    原文:利用修改div的位置+js对象存储div信息 实现简单的div自定义布局功能 利用修改div的位置+js对象存储div信息 实现简单的div自定义布局功能1.在界面上添加几个checkbox和一 ...

  7. Android开发学习之路--UI之自定义布局和控件

    新的一年已经开始了,今天已经是初二了,两天没有学习了,还是要来继续学习下.一般手机的title都是actionbar,就像iphone一样可以后退,可以编辑.这里自定义布局就来实现下这个功能,首先准备 ...

  8. 【转】Android AlertDialog自定义布局

    原文网址:https://blog.csdn.net/u010694658/article/details/53022294 由于开发中经常使用弹框,然而系统自带的弹框太局限,也不太美观,经常不能满足 ...

  9. form-create教程:自定义布局,实现一行多个组件

    本文将介绍form-create如何自定义布局,实现一行多个组件 form-create 是一个可以通过 JSON 生成具有动态渲染.数据收集.验证和提交功能的表单生成器.并且支持生成任何 Vue 组 ...

随机推荐

  1. elk收集分析nginx access日志

    elk收集分析nginx access日志 首先elk的搭建按照这篇文章使用elk+redis搭建nginx日志分析平台说的,使用redis的push和pop做队列,然后有个logstash_inde ...

  2. 基于HTML5的WebGL结合Box2DJS物理引擎应用

    上篇我们基于HT for Web呈现了A* Search Algorithm的3D寻路效果,这篇我们将采用HT for Web 3D来呈现Box2DJS物理引擎的碰撞效果,同上篇其实Box2DJS只是 ...

  3. jquery 进阶

    1.0 jquery的ajax同步和异步区别 2.0 cdnjquery加载失败加载本地 <script type="text/javascript" src="/ ...

  4. 使用powerdesigner创建数据库表

    (1 )新建概念模型 (2 )新建表,添加表各个属性 填写属性名称和类型,主键要勾选上P,M,D. (3) 如何各个表中有相同的字段名,需要设置Tool->Model Options,把红色区域 ...

  5. 【UWP】批量修改图标尺寸

    UWP开发中项目用到的图标资源非常多,通常每一种图标都有几种不同的尺寸,一般来说,我的项目所有Package.appxmanifest用到的图标就有40个,通常这些图标都是一样的,只是尺寸大小不一而已 ...

  6. Mac OS 的一点历史: Mac OS, Mac OSX 与Darwin

    作为收购 NeXT 公司的结果,苹果公司获得了 NeXTSTEP 架构中的 Mach 和 Objective-C 等设计.尽管 NeXTSTEP 本身已经不再发展了,但是其中的组件在 OS X 中获得 ...

  7. 第 15 章 CSS 文本样式[下]

    学习要点: 1.文本总汇 2.文本样式 3.文本控制 主讲教师:李炎恢 本章主要探讨 HTML5 中 CSS 文本样式,通过文本样式的设置,更改字体的大小.样式以及文本的方位. 一.文本总汇 本节课, ...

  8. [moka同学笔记]Yii2中多表关联查询(join、joinwith) (摘录)

    表结构 现在有客户表.订单表.图书表.作者表, 客户表Customer   (id  customer_name) 订单表Order          (id  order_name       cu ...

  9. HR人力资源战略流程制定

    HR人力资源战略 是指根据企业总体战略的要求,为适应企业生存和发展的需要,对企业人力资源进行开发,提高职工队伍的整体素质,从中发现和培养出一大批优秀人才,所进行的长远性的人力资源管理方面的专业谋划和方 ...

  10. 高性能 Windows Socket 组件 HP-Socket v2.2.3 正式发布

    HP-Socket 是一套通用的高性能 Windows Socket 组件包,包含服务端组件(IOCP 模型)和客户端组件(Event Select 模型),广泛适用于 Windows 平台的 TCP ...