UIButton实现上图下字,左图右字等组合形式以及sizeToFit的简单理解
2016-11-04 18:11
309 查看
UI需求中很会遇到很多文字和图片混排的效果,暴力做法就是图片用Image,文字用Label分开来实现,然后组合,
但是我们有UIButton,可以根据他的imageEdgeInsets和titleEdgeInsets来实现需要的效果
![](http://img.blog.csdn.net/20161105094047349)
最终四种效果如上图,最后还附带了虚线的画法
Demo:点击打开链接
我们默认情况下给UIButton设置image和titile之后是这样的
![](http://img.blog.csdn.net/20161104165408870)
左边图片和右边文字,默认居中,而且紧靠着
那么UIButton暴露了两个属性来修改相对位置,需要注意的是
This property is used only for positioning the image during layout. The button does
not use this property to determine
这句话的意思是这个属性只是修改其相对位置,不会通过这个属性来改变UIButton的内部大小的
下图是更改后的两个效果
![](http://img.blog.csdn.net/20161104180937645)
![](http://img.blog.csdn.net/20161104180937645)
![](http://img.blog.csdn.net/20161104165750296)
![](http://img.blog.csdn.net/20161104165759499)
可以看出打印结果,根本影响不了其内在本质的大小,也就是UIButton就这么大,无论你偏移去哪了,那么这个时候你点击了“文字”是不会触发事件的,你也可以看出,他的大小根本没有改变
这样不是我们要的最终效果啊,如果大小不进行相应的扩充,那么不是白搞了,就好比外表变了,本质还是没变,一样不适用,看下面这句话
But there is a
property that can help, and that's
docs for that say, in part:
The button uses this property to determine
这句话就是让我们根据其他属性进一步进行content的扩充
最终我们要的效果就是
![](http://img.blog.csdn.net/20161104170303271)
2016-11-04 17:02:30.546 UIButtonEdge[6198:366700] wowowowoowowowowowowow{166, 21}
打印结果和效果都出来了,这样UI变了,UIButton的content也跟着变大了,点击事件正常执行,就能满足我们的需求了
逻辑大概是这么个逻辑,我们分解下,那么首先你得明白Image和titile的相对位置
跟tableView的contentInset是类似的,
如果只有title,那它上下左右都是相对于button的,image也是一样;
如果同时有image和label,那这时候image的上左下是相对于button,右边是相对于label的;title的上右下是相对于button,左边是相对于image的。
下面四种用到的变量
1.图片在左边,文字在右边(默认的)
![](http://img.blog.csdn.net/20161104171958357)
2.图片在右边,文字在左边
![](http://img.blog.csdn.net/20161104172245907)
3.图片在上面,文字在下面
![](http://img.blog.csdn.net/20161104174203200)
4.文字在上面,图片在下面
![](http://img.blog.csdn.net/20161104174300514)
注:这上面四种ContentEdgeInsets都是扩充或者缩小移动后的Button大小的,这样保证了效果也保证了点击事
件,感觉没必要再单独封装成Category了,直接调用也很简单,需要的自行可以参考下
![](http://img.blog.csdn.net/20161104181101862)
![](http://img.blog.csdn.net/20161104181101862)
这里涉及到contentInsets的变化,UIButton的这种情况需要手动更改,我们另一种实现(测试UILabel)
sizeThatFits 和 sizeToFit
- (CGSize)sizeThatFits:(CGSize)size; // return 'best' size to fit given size. does not actually resize
view. Default is return existing view size
- (void)sizeToFit; // calls sizeThatFits: with current view bounds and changes bounds size.
注释的个人理解:
当我们调用sizeToFit的时候,会call sizeThatFits来计算出best size来适应内在控件的最小尺寸,而且该方法还会change bounds size,就是直接更改调用者的frame
而直接调用sizeThatFits只是计算出最适合内部控件的size返回,仅此而已,根本不会更改调用者的frame
直接看代码的打印来的直接点
11.11更新 (通过该方法获取WebView的高度)
有时候需要根据不同的内容调整UIWebView的高度,以使UIWebView刚好装下所有内容,不用拖动,后面也不会留白。有两种方式可根据加载内容获取UIWebView的合适高度,但都需要在网页内容加载完成后才可以,即需要在webViewDidFinishLoad回调中使用
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView.frame = frame;
}
sizeThatFits方法有个问题,如果当前UIView的大小比刚好合适的大小还大,则返回当前的大小,不会返回最合适的大小值,所以使用sizeThatFits前,先将UIWebView的高度设为最小,即1,然后再使用sizeThatFits就会返回刚好合适的大小。
另一种方法
- (void)webViewDidFinishLoad:(UIWebView *)webView
{ CGRect frame = webView.frame;
NSString *fitHeight = [webview stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"];
frame.size.height = [fitHeight floatValue];
webView.frame = frame;
}
一个非常简单易懂的Demo地址:点击打开链接
![](http://img.blog.csdn.net/20161104180937645)
![](http://img.blog.csdn.net/20161104180937645)
![](http://img.blog.csdn.net/20161104180937645)
但是我们有UIButton,可以根据他的imageEdgeInsets和titleEdgeInsets来实现需要的效果
最终四种效果如上图,最后还附带了虚线的画法
Demo:点击打开链接
我们默认情况下给UIButton设置image和titile之后是这样的
左边图片和右边文字,默认居中,而且紧靠着
那么UIButton暴露了两个属性来修改相对位置,需要注意的是
This property is used only for positioning the image during layout. The button does
not use this property to determine
intrinsicContentSizeand
sizeThatFits:
这句话的意思是这个属性只是修改其相对位置,不会通过这个属性来改变UIButton的内部大小的
下图是更改后的两个效果
NSLog(@"wowowowoowowowowowowow%@",NSStringFromCGSize(self.button.intrinsicContentSize)); 2016-11-04 16:57:20.204 UIButtonEdge[6173:359806] wowowowoowowowowowowow{66, 21}
可以看出打印结果,根本影响不了其内在本质的大小,也就是UIButton就这么大,无论你偏移去哪了,那么这个时候你点击了“文字”是不会触发事件的,你也可以看出,他的大小根本没有改变
这样不是我们要的最终效果啊,如果大小不进行相应的扩充,那么不是白搞了,就好比外表变了,本质还是没变,一样不适用,看下面这句话
But there is a
property that can help, and that's
contentEdgeInsets. The
docs for that say, in part:
The button uses this property to determine
intrinsicContentSizeand
sizeThatFits:.
这句话就是让我们根据其他属性进一步进行content的扩充
最终我们要的效果就是
2016-11-04 17:02:30.546 UIButtonEdge[6198:366700] wowowowoowowowowowowow{166, 21}
打印结果和效果都出来了,这样UI变了,UIButton的content也跟着变大了,点击事件正常执行,就能满足我们的需求了
逻辑大概是这么个逻辑,我们分解下,那么首先你得明白Image和titile的相对位置
跟tableView的contentInset是类似的,
如果只有title,那它上下左右都是相对于button的,image也是一样;
如果同时有image和label,那这时候image的上左下是相对于button,右边是相对于label的;title的上右下是相对于button,左边是相对于image的。
下面四种用到的变量
CGFloat gap = 10.f; CGFloat labelWidth = self.button.titleLabel.bounds.size.width; CGFloat imageWidth = self.button.imageView.bounds.size.width; CGFloat imageHeight = self.button.imageView.bounds.size.height; CGFloat labelHeight = self.button.titleLabel.bounds.size.height; // 这里都计算完毕了,很简单,例如 imageWidth是A labelWidth是B // 那么image要居中就要X轴移动 (A+B)/2 - A/2 // label要居中就要X轴移动 (A+B)/2 - B/2 // Y轴移动就直接除以2 然后加上间隙就好了 // 图片中心对齐控件XY轴的偏移量 CGFloat imageOffSetX = labelWidth / 2; CGFloat imageOffSetY = imageHeight / 2 + gap / 2; CGFloat labelOffSetX = imageWidth / 2; CGFloat labelOffSetY = labelHeight / 2 + gap / 2;
1.图片在左边,文字在右边(默认的)
// 左图右字 CGFloat gap = 10.f; self.button.imageEdgeInsets = UIEdgeInsetsMake(0, -gap / 2, 0, gap / 2); self.button.titleEdgeInsets = UIEdgeInsetsMake(0, gap / 2, 0 , - gap / 2); self.button.contentEdgeInsets = UIEdgeInsetsMake(0, gap / 2, 0, gap / 2);
2.图片在右边,文字在左边
// 右图左字 CGFloat gap = 10.f; self.button2.imageEdgeInsets = UIEdgeInsetsMake(0,labelWidth + gap / 2 , 0, -labelWidth - gap / 2); self.button2.titleEdgeInsets = UIEdgeInsetsMake(0, -imageWidth - gap / 2, 0, imageWidth+gap / 2); self.button2.contentEdgeInsets = UIEdgeInsetsMake(0, gap / 2, 0, gap / 2);
3.图片在上面,文字在下面
// 上图下字 // 让UIButton能保证边缘自适应 居中的时候需要 // 当上下排布的时候,要根据edge来填充content大小 CGFloat maxWidth = MAX(imageWidth,labelWidth); // 上下排布宽度肯定变小 获取最大宽度的那个 CGFloat changeWidth = imageWidth + labelWidth - maxWidth; // 横向缩小的总宽度 CGFloat maxHeight = MAX(imageHeight,labelHeight); // 获取最大高度那个 (就是水平默认排布的时候的原始高度) CGFloat changeHeight = imageHeight + labelHeight + gap - maxHeight; // 总高度减去原始高度就是纵向宽大宗高度 self.button4.imageEdgeInsets = UIEdgeInsetsMake(-imageOffSetY, imageOffSetX, imageOffSetY, -imageOffSetX); self.button4.titleEdgeInsets = UIEdgeInsetsMake(labelOffSetY, -labelOffSetX, -labelOffSetY, labelOffSetX); self.button4.contentEdgeInsets = UIEdgeInsetsMake(changeHeight - labelOffSetY, - changeWidth / 2, labelOffSetY, -changeWidth / 2);
4.文字在上面,图片在下面
// 上字下图 // 让UIButton能保证边缘自适应 居中的时候需要 // 当上下排布的时候,要根据edge来填充content大小 CGFloat maxWidth = MAX(imageWidth,labelWidth); // 上下排布宽度肯定变小 获取最大宽度的那个 CGFloat changeWidth = imageWidth + labelWidth - maxWidth; // 横向缩小的总宽度 CGFloat maxHeight = MAX(imageHeight,labelHeight); // 获取最大高度那个 (就是水平默认排布的时候的原始高度) CGFloat changeHeight = imageHeight + labelHeight + gap - maxHeight; // 总高度减去原始高度就是纵向宽大宗高度 self.button6.imageEdgeInsets = UIEdgeInsetsMake(imageOffSetY, imageOffSetX, -imageOffSetY, -imageOffSetX); self.button6.titleEdgeInsets = UIEdgeInsetsMake(-labelOffSetY, -labelOffSetX, labelOffSetY, labelOffSetX); self.button6.contentEdgeInsets = UIEdgeInsetsMake(labelOffSetY, -changeWidth / 2, changeHeight - labelOffSetY, -changeWidth / 2);
注:这上面四种ContentEdgeInsets都是扩充或者缩小移动后的Button大小的,这样保证了效果也保证了点击事
件,感觉没必要再单独封装成Category了,直接调用也很简单,需要的自行可以参考下
这里涉及到contentInsets的变化,UIButton的这种情况需要手动更改,我们另一种实现(测试UILabel)
sizeThatFits 和 sizeToFit
- (CGSize)sizeThatFits:(CGSize)size; // return 'best' size to fit given size. does not actually resize
view. Default is return existing view size
- (void)sizeToFit; // calls sizeThatFits: with current view bounds and changes bounds size.
注释的个人理解:
当我们调用sizeToFit的时候,会call sizeThatFits来计算出best size来适应内在控件的最小尺寸,而且该方法还会change bounds size,就是直接更改调用者的frame
而直接调用sizeThatFits只是计算出最适合内部控件的size返回,仅此而已,根本不会更改调用者的frame
直接看代码的打印来的直接点
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 64, 0, 0)]; label.backgroundColor = [UIColor redColor]; label.font = [UIFont systemFontOfSize:18]; label.text = @"呵呵呵呵"; CGSize sizeThatFit = [label sizeThatFits:CGSizeMake(1000, 1000)]; NSLog(@"sizeThatFit------> width = %lf,height = %lf",sizeThatFit.width,sizeThatFit.height); // sizeThatFit------> width = 73.500000,height = 21.500000 NSLog(@"sizeThatFit之后的labelFrame ------> width = %lf,height = %lf",label.frame.size.width,label.frame.size.height); // sizeThatFit之后的labelFrame ------> width = 0.000000,height = 0.000000 没有变化 只是返回值而已,不改变调用者frame [label sizeToFit]; NSLog(@"sizeTofit之后的labelFrame ——----> width = %lf.height = %lf",label.frame.size.width,label.frame.size.height); //sizeTofit之后的labelFrame ——----> width = 73.500000.height = 21.500000 第一计算frame,第二根据sizeThatFit计算返回的frame改变调用者frame
11.11更新 (通过该方法获取WebView的高度)
有时候需要根据不同的内容调整UIWebView的高度,以使UIWebView刚好装下所有内容,不用拖动,后面也不会留白。有两种方式可根据加载内容获取UIWebView的合适高度,但都需要在网页内容加载完成后才可以,即需要在webViewDidFinishLoad回调中使用
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView.frame = frame;
}
sizeThatFits方法有个问题,如果当前UIView的大小比刚好合适的大小还大,则返回当前的大小,不会返回最合适的大小值,所以使用sizeThatFits前,先将UIWebView的高度设为最小,即1,然后再使用sizeThatFits就会返回刚好合适的大小。
另一种方法
- (void)webViewDidFinishLoad:(UIWebView *)webView
{ CGRect frame = webView.frame;
NSString *fitHeight = [webview stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"];
frame.size.height = [fitHeight floatValue];
webView.frame = frame;
}
一个非常简单易懂的Demo地址:点击打开链接
相关文章推荐
- java 关于Spring中Aop的简单理解以及SpringBoot如何添加Aop实现步骤
- 排列和组合简单的递归思路以及C++实现
- c++中capacity和size的区别,以及reserve和resize的区别,shink_to_fit用法
- UILabel如何使用sizeToFit进行宽高适配 和 sizeThatFits 以及实现总是顶端显示text的需求
- java多线程理解 以及java实现的简单的死锁
- UIButton的sizeToFit方法无效
- JDBC的基本概念理解以及简单实现
- 对Thread类的继承、Runable接口的实现,以及线程池的简单理解
- ScrollTo,ScrollBy,offsetLeftAndRight,offsetTopAndBottom以及侧滑的简单实现
- 线程池技术个人理解以及c语言的简单实现
- WinAPI回调函数的理解与查找制定标题窗口的实现(以参数形式传入回调函数)
- Asp.net中创建程序集以及一个简单的IHttpHandler 实现
- 理解“UML类间的五种关系,也是对代码实现形式的一种约束”
- 如何应用Asp.Net Mvc内建功能(DefaultModelBinder)实现简单类型、复杂类型、集合类型,以及字典类型的自动绑定
- 出现Error: must call SetScrollSizes() or SetScaleToFitSize()
- 深入理解C++对象模型-成员函数的本质以及虚函数的实现(非虚继承)
- linq to access 简单实现
- Mashups简介以及简单实现分析
- JAVA简单实现不区分大小写以及空格比较字符串
- 窗体间参数传递&以及事件的简单理解