UIButton的九种常见布局
2018-08-21 本文已影响40人
三生之二
本文解决UIButton常见的九种布局,上中下,左中右,以及文字和图片之间的距离问题。
git链接如下:https://github.com/Sameny/UIButton-STAlignment
/ 重要
支持UIButton常见排列
请在button的frame确定之后调用
如在viewWillAppear之后货layoutSubviews方法中
/
首先定义一些枚举:
1.文字和图片朝向:
typedef NS_ENUM(NSUInteger, STContentAlignOrientation) {
STContentAlignOrientationVertical,
STContentAlignOrientationHorizontal,
};
2.定义文字和图片整体的content的9个位置
typedef NS_ENUM(NSUInteger, STContentAlignment) {
STContentAlignmentLeft,
STContentAlignmentCenter,
STContentAlignmentRight,
STContentAlignmentTopLeft,
STContentAlignmentTopCenter,
STContentAlignmentTopRight,
STContentAlignmentBottomLeft,
STContentAlignmentBottomCenter,
STContentAlignmentBottomRight,
};
- 定义几种常用方法
- (void)verticalAlignmentWithSpace:(CGFloat)space imageAtTop:(BOOL)imageAtTop;
- (void)horizontalAlignmentWithSpace:(CGFloat)space imageAtLeft:(BOOL)imageAtLeft;
/**
水平方向设置UIButton中的文字和图片对齐方式
@param space 文案和图片之间的间距
@param imageAtTop YES:图片在上
@param alignment 整体内容对齐方式
*/
- (void)verticalAlignmentWithSpace:(CGFloat)space imageAtTop:(BOOL)imageAtTop alignment:(STContentAlignment)alignment;
/**
水平方向设置UIButton中的文字和图片对齐方式
@param space 文案和图片之间的间距
@param imageAtLeft YES:图片在左
@param alignment 整体内容对齐方式
*/
- (void)horizontalAlignmentWithSpace:(CGFloat)space imageAtLeft:(BOOL)imageAtLeft alignment:(STContentAlignment)alignment;
/**
设置UIButton中的文字和图片对齐方式
@param alignOrientation 垂直/水平放置文案和图片
@param space 文案和图片之间的间距
@param imageAtHead YES:图片在前(上/左)
@param alignment 整体内容对齐方式
*/
- (void)alignmentWithContentAlignOrientation:(STContentAlignOrientation)alignOrientation space:(CGFloat)space imageAtHead:(BOOL)imageAtHead alignment:(STContentAlignment)alignment;
4.核心代码实现
其他方法都是调用该方法实现
- (void)alignmentWithContentAlignOrientation:(STContentAlignOrientation)alignOrientation space:(CGFloat)space imageAtHead:(BOOL)imageAtHead alignment:(STContentAlignment)alignment {
NSString *title = self.titleLabel.text;
UIFont *font = self.titleLabel.font;
UIImage *image = self.imageView.image;
if (!title && !image) return;
CGFloat h_delta = 0;
CGFloat v_delta = 0;
CGFloat centerOffsetY = 0; // 只在STContentAlignOrientationVertical时生效
// CGSize textSize = title?[title sizeWithAttributes:@{NSFontAttributeName:font}]:CGSizeZero;
CGSize textSize = self.titleLabel.intrinsicContentSize;
if (CGSizeEqualToSize(CGSizeZero, textSize) && title.length) {
textSize = [title sizeWithAttributes:@{NSFontAttributeName:font}];
}
CGSize imageSize = image?image.size:CGSizeZero;
space = space/2; // 文字和图像各移动一半,保证整体对齐
if (alignOrientation == STContentAlignOrientationHorizontal) {
if (imageAtHead) {
[self setImageEdgeInsets:UIEdgeInsetsMake(0, -space, 0, space)];
[self setTitleEdgeInsets:UIEdgeInsetsMake(0, space, 0, -space)];
}
else {
[self setImageEdgeInsets:UIEdgeInsetsMake(0, textSize.width + space, 0, -textSize.width - space)];
[self setTitleEdgeInsets:UIEdgeInsetsMake(0, -imageSize.width - space, 0, imageSize.width + space)];
}
h_delta = (self.bounds.size.width - textSize.width - imageSize.width)/2.f - space;
v_delta = (self.bounds.size.height - MAX(textSize.height, imageSize.height))/2.f;
}
else {
if (imageAtHead) {
[self setImageEdgeInsets:UIEdgeInsetsMake(-imageSize.height/2 - space, textSize.width/2, imageSize.height/2 + space, -textSize.width/2)];
[self setTitleEdgeInsets:UIEdgeInsetsMake(textSize.height/2 + space, -imageSize.width/2, -textSize.height/2 - space, imageSize.width/2)];
}
else {
[self setImageEdgeInsets:UIEdgeInsetsMake(imageSize.height/2 + space, textSize.width/2, -imageSize.height/2 - space, -textSize.width/2)];
[self setTitleEdgeInsets:UIEdgeInsetsMake(-textSize.height/2 - space, -imageSize.width/2, textSize.height/2 + space, imageSize.width/2)];
}
h_delta = (self.bounds.size.width - MAX(textSize.width, imageSize.width))/2.f;
v_delta = (self.bounds.size.height - textSize.height - imageSize.height)/2.f - space;
/** 思想
1. 假定offset > 0
a.当我们的整体需要往上偏移的时候,top = -offset,bottom = offset
b.当我们的整体需要往下偏移的时候,top = offset,bottom = -offset
2. 假定offset < 0
a.当我们的整体需要往上偏移的时候,top = offset,bottom = -offset
b.当我们的整体需要往下偏移的时候,top = -offset,bottom = offset
*/
centerOffsetY = (textSize.height - imageSize.height)/2.f; // 中心相对偏移量,如果centerOffsetY > 0,说明需要整体向image方向移动;反之向text方向移动
if (!imageAtHead) {
centerOffsetY *= -1.f; // 这样就转换成 centerOffsetY > 0,则往上移动;centerOffsetY < 0,则往下移动。这样就使offset = abs(centerOffsetY),centerOffsetY的正负性就代表了需要移动的方向。这样就和思想重合了
}
}
switch (alignment) {
case STContentAlignmentLeft:
[self setContentEdgeInsets:UIEdgeInsetsMake(-centerOffsetY, -h_delta, centerOffsetY, h_delta)];
break;
case STContentAlignmentCenter:
[self setContentEdgeInsets:UIEdgeInsetsMake(-centerOffsetY, 0, centerOffsetY, 0)];
break;
case STContentAlignmentRight:
[self setContentEdgeInsets:UIEdgeInsetsMake(-centerOffsetY, h_delta, centerOffsetY, -h_delta)];
break;
case STContentAlignmentTopLeft:
[self setContentEdgeInsets:UIEdgeInsetsMake(-v_delta - centerOffsetY, -h_delta, v_delta + centerOffsetY, h_delta)];
break;
case STContentAlignmentTopCenter:
[self setContentEdgeInsets:UIEdgeInsetsMake(-v_delta - centerOffsetY, 0, v_delta + centerOffsetY, 0)];
break;
case STContentAlignmentTopRight:
[self setContentEdgeInsets:UIEdgeInsetsMake(-v_delta - centerOffsetY, h_delta, v_delta + centerOffsetY, -h_delta)];
break;
case STContentAlignmentBottomLeft:
[self setContentEdgeInsets:UIEdgeInsetsMake(v_delta - centerOffsetY, -h_delta, -v_delta + centerOffsetY, h_delta)];
break;
case STContentAlignmentBottomCenter:
[self setContentEdgeInsets:UIEdgeInsetsMake(v_delta - centerOffsetY, 0, -v_delta + centerOffsetY, 0)];
break;
case STContentAlignmentBottomRight:
[self setContentEdgeInsets:UIEdgeInsetsMake(v_delta - centerOffsetY, h_delta, -v_delta + centerOffsetY, -h_delta)];
break;
}
}
5.提供一些常用的简单的方法,方便使用
- (void)verticalAlignmentWithSpace:(CGFloat)space imageAtTop:(BOOL)imageAtTop {
[self alignmentWithContentAlignOrientation:STContentAlignOrientationVertical space:space imageAtHead:imageAtTop alignment:STContentAlignmentCenter];
}
- (void)horizontalAlignmentWithSpace:(CGFloat)space imageAtLeft:(BOOL)imageAtLeft {
[self alignmentWithContentAlignOrientation:STContentAlignOrientationHorizontal space:space imageAtHead:imageAtLeft alignment:STContentAlignmentCenter];
}
- (void)verticalAlignmentWithSpace:(CGFloat)space imageAtTop:(BOOL)imageAtTop alignment:(STContentAlignment)alignment {
[self alignmentWithContentAlignOrientation:STContentAlignOrientationVertical space:space imageAtHead:imageAtTop alignment:alignment];
}
- (void)horizontalAlignmentWithSpace:(CGFloat)space imageAtLeft:(BOOL)imageAtLeft alignment:(STContentAlignment)alignment {
[self alignmentWithContentAlignOrientation:STContentAlignOrientationHorizontal space:space imageAtHead:imageAtLeft alignment:alignment];
}