Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

UIButton实现上图下字,左图右字等组合形式以及sizeToFit的简单理解

$
0
0

    UI需求中很会遇到很多文字和图片混排的效果,暴力做法就是图片用Image,文字用Label分开来实现,然后组合,

是我们有UIButton,可以根据他的imageEdgeInsets和titleEdgeInsets来实现需要的效果




我们默认情况下给UIButton设置image和titile之后是这样的


左边图片和右边文字,默认居中,而且紧靠着


那么UIButton暴露了两个属性来修改相对位置,需要注意的是

This property is used only for positioning the image during layout. The button does not use this property to determine intrinsicContentSize and 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 contentEdgeInsetsThe docs for that say, in part:

The button uses this property to determine intrinsicContentSize and 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的

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





作者:Deft_MKJing 发表于2016/11/4 18:11:24 原文链接
阅读:47 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>