逻辑思路:
button设置图片和文字后后再设置titleEdgeInsets属性和 imageEdgeInsets属性实现button的上图下文,上文下图,左图右文,右图左文的重新排列(自由设置图文间距)

UIEdgInsets官方解释:

Edge inset values are applied to a rectangle to shrink or expand the area represented by that rectangle. Typically, edge insets are used during view layout to modify the view’s frame. Positive values cause the frame to be inset (or shrunk) by the specified amount. Negative values cause the frame to be outset (or expanded) by the specified amount.

意思就是:UIEdgInsets是用来扩大或者缩小控件的矩形区域,通常在视图布局期间修改视图框架,正值缩小视图框架, 负值扩大视图框架

##左文右图
默认情况下,button的image和label是紧贴着居中的,那如果想要image在右边,label在左边应该怎么办呢?

答案就是:

self.imageEdgeInsets = UIEdgeInsetsMake(0, labelWidth + spacing/2, 0, -(labelWidth + spacing/2));
self.titleEdgeInsets = UIEdgeInsetsMake(0, -(imageHeight + spacing/2), 0, imageHeight + spacing/2);

其实就是这一句:This property is used only for positioning the image during layout
其实titleEdgeInsets属性和 imageEdgeInsets属性只是在画这个button出来的时候用来调整image和label位置的属性,并不影响button本身的大小。
UIEdgeInsetsMake(CGFloat top, CGFloat left, CGFloat bottom, CGFloat right)

它们只是image和button相较于原来位置的偏移量,那什么是原来的位置呢?就是没有设置edgeInset时候的位置了
imageEdgeInsets,titleEdgeInsets默认为0,spacing为图片文字间隔
如果image在右边,label在左边,二者的上下的偏移量相较于原来的位置没有改变,为0。

左右偏移量的计算:

偏移的距离
imageOffset = | 初始X - 修改后X | = orgLabW + spacing/2

备注

  • orgLabW 代表titleLable在button内部的初始(original)显示宽度,当button的宽度不够时,titleLable会被压缩,此时宽度小于完全显示时的真实宽度trueLabW,参见后图。
  • 宽度不够的情况下titleLable会优先被压缩,imageView的宽度一般是正确的
  • 此处认为orgLabH = trueLabH,没有考虑label多行显示的情形

正负值判断
假设只改变image的一条边距的偏移量,如果image缩小,偏移量为正,反之为负;
self.imageEdgeInsets = UIEdgeInsetsMake(0, orgLabW + spacing/2, 0, -(orgLabW + spacing/2));
label计算过程同理:
self.titleEdgeInsets = UIEdgeInsetsMake(0, -(imgW + spacing/2), 0, imgW + spacing/2);
##上图下文

上图下文和上文下图计算方式一样(实际四种模式计算方式都一样),下面就以上图下文的计算为例。

偏移距离
imageOffsetX = labW/2
imageOffsetY = labH/2 + spacing/2
labelOffsetX = imgW/2
labelOffsetY = imgH/2 + spacing/2

提示:
在实际应用中发现这种情况在button的宽度大于 ImageWidth+lableWidth是没有问题的,但是当小于的时候就不行了



##为什么呢##
比较上两张图发现lable中心点的位置是正确的,只是左右的边缘的偏移量(决定宽度)没有计算好,ImageView的中心点位置是错误的,大小是正确的。

CGFloat labelWidth = [self.titleLabel.text sizeWithAttributes:@{NSFontAttributeName:self.titleLabel.font}].width;
CGFloat labelHeight = [self.titleLabel.text sizeWithAttributes:@{NSFontAttributeName:self.titleLabel.font}].height;

这里计算的是lable的真实宽度,而button宽度不够时,label会被压缩的显示宽度是小于真是宽度的,我们在重新排列的时候计算Image中心点的位置应该用lable的显示宽度而不是真实宽度。
同样,计算lable左右边缘的偏移量也应该把lable的真实宽度考虑进去,详情见下图
X1,X2分别为lable的左右边缘x值。

偏移距离

//image中心移动的x距离
CGFloat imageOffsetX = orgLabW /2 ;
//image中心移动的y距离
CGFloat imageOffsetY = orgLabH / 2 + spacing / 2;
//label左边缘移动的x距离
CGFloat labelOffsetX1 = imgW/2 - orgLabW/2 + trueLabW/2;
//label右边缘移动的x距离
CGFloat labelOffsetX2 = imgW/2 + orgLabW/2 - trueLabW/2;
//label中心移动的y距离
CGFloat labelOffsetY = imgH / 2 + spacing / 2;

注意:当button宽度够大时 orgLabW = trueLabW此时labelOffsetX1 = labelOffsetX2 = imgW/2和上面情况一样一样的,也就是说这种计算方法也适用于上面的情景

正负值判断后结果为
self.imageEdgeInsets = UIEdgeInsetsMake(-imageOffsetY, imageOffsetX, imageOffsetY, -imageOffsetX);
self.titleEdgeInsets = UIEdgeInsetsMake(labelOffsetY, -labelOffsetX1, -labelOffsetY, labelOffsetX2);
##上文下图

偏移距离

//image中心移动的x距离
CGFloat imageOffsetX = orgLabW /2 ;
//image中心移动的y距离
CGFloat imageOffsetY = orgLabH / 2 + spacing / 2;
//label左边缘移动的x距离
CGFloat labelOffsetX1 = imgW/2 - orgLabW/2 + trueLabW/2;
//label右边缘移动的x距离
CGFloat labelOffsetX2 = imgW/2 + orgLabW/2 - trueLabW/2;
//label中心移动的y距离
CGFloat labelOffsetY = imgH / 2 + spacing / 2;

结果竟然跟上面一样,说明这种方法有点笨了,肯定有不同的理解方法与解决方案,在这里就抛砖引玉了,欢迎交流。

正负值判断后结果为
self.imageEdgeInsets = UIEdgeInsetsMake(imageOffsetY, imageOffsetX, -imageOffsetY, -imageOffsetX);
self.titleEdgeInsets = UIEdgeInsetsMake(-labelOffsetY, -labelOffsetX1, labelOffsetY, labelOffsetX2);
##实际应用

这些处理是专门对Button进行的,最好的应用场景当然是写到Button的Category 里面,方便外面调用。

#import <UIKit/UIKit.h>typedef NS_ENUM(NSInteger, ZXImagePosition) {ZXImagePositionLeft     = 0,            //图片在左,文字在右,默认ZXImagePositionRight    = 1,            //图片在右,文字在左ZXImagePositionTop      = 2,            //图片在上,文字在下ZXImagePositionBottom   = 3,            //图片在下,文字在上
};@interface UIButton (ChaoGe)/***  利用UIButton的titleEdgeInsets和imageEdgeInsets来实现文字和图片的自由排列*  注意:这个方法需要在设置图片和文字之后才可以调用,且button的大小要大于 图片大小+spacing**  @param spacing 图片和文字的间隔*/
- (void)setImagePosition:(ZXImagePosition)postion spacing:(CGFloat)spacing;@end
#import "UIButton+ChaoGe.h"@implementation UIButton (ChaoGe)- (void)setImagePosition:(ZXImagePosition)postion spacing:(CGFloat)spacing {CGFloat imgW = self.imageView.image.size.width;CGFloat imgH = self.imageView.image.size.height;CGSize origLabSize = self.titleLabel.bounds.size;CGFloat orgLabW = origLabSize.width;CGFloat orgLabH = origLabSize.height;CGSize trueSize = [self.titleLabel sizeThatFits:CGSizeMake(MAXFLOAT, MAXFLOAT)];CGFloat trueLabW = trueSize.width;//image中心移动的x距离CGFloat imageOffsetX = orgLabW/2 ;//image中心移动的y距离CGFloat imageOffsetY = orgLabH/2 + spacing/2;//label左边缘移动的x距离CGFloat labelOffsetX1 = imgW/2 - orgLabW/2 + trueLabW/2;//label右边缘移动的x距离CGFloat labelOffsetX2 = imgW/2 + orgLabW/2 - trueLabW/2;//label中心移动的y距离CGFloat labelOffsetY = imgH/2 + spacing/2;switch (postion) {case ZXImagePositionLeft:self.imageEdgeInsets = UIEdgeInsetsMake(0, -spacing/2, 0, spacing/2);self.titleEdgeInsets = UIEdgeInsetsMake(0, spacing/2, 0, -spacing/2);break;case ZXImagePositionRight:self.imageEdgeInsets = UIEdgeInsetsMake(0, orgLabW + spacing/2, 0, -(orgLabW + spacing/2));self.titleEdgeInsets = UIEdgeInsetsMake(0, -(imgW + spacing/2), 0, imgW + spacing/2);break;case ZXImagePositionTop:self.imageEdgeInsets = UIEdgeInsetsMake(-imageOffsetY, imageOffsetX, imageOffsetY, -imageOffsetX);self.titleEdgeInsets = UIEdgeInsetsMake(labelOffsetY, -labelOffsetX1, -labelOffsetY, labelOffsetX2);break;case ZXImagePositionBottom:self.imageEdgeInsets = UIEdgeInsetsMake(imageOffsetY, imageOffsetX, -imageOffsetY, -imageOffsetX);self.titleEdgeInsets = UIEdgeInsetsMake(-labelOffsetY, -labelOffsetX1, labelOffsetY, labelOffsetX2);break;default:break;}}@end

##注意事项

  • 在设置图片和文字之后,并且button的size不能为0调用本方法才能计算出正确的偏移量。
  • 本次更新此方法已经适配了button的宽度小于 imageView+titleLable宽度和的情况,但是button的大小至少要大于图片的大小。
  • 每次修改button文字后都要再调用一下该方法,否则排版可能会混乱。

UIButton 的图文混排相关推荐

  1. XMPP键盘订制实现图文混排

    在现阶段的通信服务中,各种标准都有,因此会出现无法实现相互连通,而XMPP(Extensible Message and presence Protocol)协议的出现,实现了整个及时通信服务协议的互 ...

  2. 类似微信表情图文混排(本地自定义表情)

    注:仅仅是提供思路 有些问题如隐藏系统自带的selectall按钮 自定义copy按钮 需要再解决 //首先引用 https://github.com/zekunyan/UITextViewDIYEm ...

  3. ios 表情符号 键盘_iOS 表情键盘+gif聊天图文混排,看我的就够了

    更新: 1.解决首次加载键盘卡顿的问题: 2.修改聊天布局方式,现在无需计算,更加丝滑. 前言: 之前做过[OC版本]和[swift版本]图文混排和表情键盘,说实在的很low,特别是键盘,整体只是实现 ...

  4. android多媒体图文混排,干货!!!Android富文本实现图文混排

    效果图 rich.jpg 像图中的效果,大家在开发并不少见,大家可能不知道android提供了实现图文混排的类.大家或许会写一个布局或者使用drawableLeft这个属性实现文本的左侧图标. and ...

  5. iOS - 图文混排技术方案分享

    前言 不少同学在工作中都能遇到图文混排的需求.但是实现图文混排的技术方案有好几种,相应的方案优劣也有差别.今天和大家一起分享一下图文混排的技术方案以及我的选择. Demo和解析工具已经开源 GitHu ...

  6. Android TextView中图文混排设置行间距导致高度不一致问题解决

    Android TextView中图文混排设置行间距导致高度不一致问题解决 参考文章: (1)Android TextView中图文混排设置行间距导致高度不一致问题解决 (2)https://www. ...

  7. android富文本图片自适应,Android Span富文本图文混排 - ImageSpan(图文垂直居中)...

    ###为文字实现很丰富的特殊效果,当然少不了图文混排 so... 直接上效果(有直接使用和自定义垂直居中效果) ##1 ImageSpan: ImageSpan(context, resourceId ...

  8. TextView图文混排,显示添加的图片,三种常用方法,亲测

    图文混排,文字就不说了,主要是显示图片的方法 1.TextView使用ImageSpan显示图片 [java] view plaincopy <span style="font-siz ...

  9. 利用ListView实现新闻客户端的新闻内容图文混排

    如图: 布局文件: <LinearLayout xmlns:android="<a href="http://schemas.android.com/apk/res/a ...

最新文章

  1. C#多线程学习(二) 如何操纵一个线程
  2. C语言求最大公约数3种方法
  3. 前端jenkins打包编译发布项目流程
  4. 2022年中国AI芯片行业深度研究
  5. 工作与生活平衡(2)运动也需要执行力
  6. python 人脸识别调整人脸大的距离_Python 人脸识别就多简单,看这个就够了!
  7. localhost和127.0.0.1有什么区别?(转载)
  8. javahost:使用虚拟DNS省掉开发环境配置hosts文件
  9. 经纬度距离计算小工具_一个NB工具大合集打网站,总有一款是你需要的
  10. SVG排版教程 | SVG排版入门基础知识汇总
  11. PPT修改母版页码格式后不管用?
  12. Rmarkdown使用rvest包实现对静态网页数据抓取
  13. inferred type_您最终可以使用var在Java中声明Inferred Type局部变量-这就是为什么它很棒...
  14. FTX交易平台与AZA Finance达成合作,推动非洲数字经济发展
  15. unity世界坐标与相对坐标转换
  16. 局域网内打印机打印只能打印一页或是几页的解决办法
  17. 如何使用Arduino制作摩尔斯电报翻译器
  18. 大学生应如何防止躺平
  19. 做回归分析时import ConvergenceWarning出错的问题
  20. java计算机毕业设计绿色生活基于PS、DW的绿色环保宣传网站源码+数据库+系统+lw文档+mybatis+运行部署

热门文章

  1. 一篇文章让你了解这个基于Raspberry Pi / 树莓派而设计的工业计算机- 2
  2. vueuse(函数库)的基本使用,宝藏神器,务必收藏
  3. 十五张思维导图带你快速学习PHP语言基础 1
  4. 如何使用Spark计算共同好友?
  5. Opencv之利用matchshape算子实现简单的形状匹配
  6. Presto 在 Lyft 的实践
  7. QT+OSG/osgEarth编译之八:webp+Qt编译(一套代码、一套框架,跨平台编译,版本:libwebp-1.2.2)
  8. MYSQL实现水平分表
  9. linux power_评估Linux on POWER的性能
  10. 网页计算机(h5+js+css)