iOS学习专题

iOS 左文右图的按钮

2019-04-19  本文已影响1人  sergeant

iOS 按钮默认布局方式是左图右文,但是有时候我们需要左文右图的布局。

下面总结了几种方案。要结论的同学直接看方案五。

方案一

直接使用UIButton,设置其semanticContentAttribute为UISemanticContentAttributeForceRightToLeft。即布局改为从右至左。这个属性原本用于阿拉伯文这种从右向左写的语言。

button.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;

优点:

缺点:

方案二

直接使用UIButton,设置其titleEdgeInsets或imageEdgeInsets。也就是让图片右移文本的宽度,文本左移图片的宽度。

button.titleEdgeInsets = UIEdgeInsetsMake(0, -button.imageView.frame.size.width, 0, button.imageView.frame.size.width);
button.imageEdgeInsets = UIEdgeInsetsMake(0, button.titleLabel.frame.size.width, 0, -button.titleLabel.frame.size.width);

优点:

缺点:

方案三

方案三是方案二的变种,即派生一个UIButton的子类,来实现titleEdgeInsets与imageEdgeInsets的自动更新。

- (void)layoutSubviews {
    [super layoutSubviews];
    
    [self updateEdgeInsets];
}

- (void)updateEdgeInsets {
    self.titleEdgeInsets = UIEdgeInsetsMake(0, -self.imageView.frame.size.width, 0, self.imageView.frame.size.width);
    self.imageEdgeInsets = UIEdgeInsetsMake(0, self.titleLabel.frame.size.width, 0, -self.titleLabel.frame.size.width);
}

之所以在layoutSubviews中调用更新方法,是因为无论是自动布局还是更改内容都会触发这个方法,并且子视图的frame都已经确定。

优点:

缺点:

方案四

派生一个UIButton的子类,通过重载 titleRectForContentRect:imageRectForContentRect: 来分别指定文本和图片的显示区域。

@interface FCReverseButton ()

@property (nonatomic, assign) CGRect originalImageRect; // 原图片区域
@property (nonatomic, assign) CGRect originalTitleRect; // 原文本区域

@end

@implementation FCReverseButton

- (CGRect)titleRectForContentRect:(CGRect)contentRect {
    if (CGRectIsEmpty(self.originalTitleRect)) {
        self.originalTitleRect = [super titleRectForContentRect:contentRect];
    }

    if (CGRectIsEmpty(self.originalTitleRect) || CGRectIsEmpty(self.originalImageRect)) {
        return self.originalTitleRect;
    } else {
        CGFloat height = MAX(CGRectGetHeight(self.originalTitleRect), CGRectGetHeight(self.originalImageRect));
        return CGRectMake(contentRect.origin.x + self.titleEdgeInsets.right, contentRect.origin.y + (height - CGRectGetHeight(self.originalTitleRect)) / 2, CGRectGetWidth(self.originalTitleRect), CGRectGetHeight(self.originalTitleRect));
    }
}

- (CGRect)imageRectForContentRect:(CGRect)contentRect {
    if (CGRectIsEmpty(self.originalImageRect)) {
        self.originalImageRect = [super imageRectForContentRect:contentRect];
    }

    if (CGRectIsEmpty(self.originalTitleRect) || CGRectIsEmpty(self.originalImageRect)) {
        return self.originalImageRect;
    } else {
        CGFloat height = MAX(CGRectGetHeight(self.originalTitleRect), CGRectGetHeight(self.originalImageRect));
        return CGRectMake(contentRect.origin.x + CGRectGetWidth(self.originalTitleRect) + self.imageEdgeInsets.right, contentRect.origin.y + (height - CGRectGetHeight(self.originalImageRect)) / 2, CGRectGetWidth(self.originalImageRect), CGRectGetHeight(self.originalImageRect));
    }
}

@end

优点:

缺点

方案五

在坐标系的层面翻转按钮的X轴,再分别将titleLabel和imageView的X轴翻转回来。可以直接对UIButton进行操作,也可以派生一个子类。建议派生一个子类。

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self horizontalReverse];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self horizontalReverse];
    }
    return self;
}

// 水平翻转
- (void)horizontalReverse {
    self.transform = CGAffineTransformMakeScale(-1, 1);
    self.imageView.transform = CGAffineTransformMakeScale(-1, 1);
    self.titleLabel.transform = CGAffineTransformMakeScale(-1, 1);
}

优点

缺点

参考:
How do I put the image on the right side of the text in a UIButton?

上一篇下一篇

猜你喜欢

热点阅读