• 干货之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, 0, 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(0, 0, 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

  • 相关阅读:
    IDEA快捷键收集
    Jmeter录制HTTPS
    Jmeter 线程组、运行次数参数化
    fiddler 抓取iphone发出的http和https包
    Appium 点击屏幕
    安卓程序如何保证低内存下依然存在
    listview
    数据库操作
    数据存储
    测试
  • 原文地址:https://www.cnblogs.com/ALongWay/p/5984805.html
Copyright © 2020-2023  润新知