@class UIImage, UIFont, UIColor, UIImageView, UILabel;
typedef NS_ENUM(NSInteger, UIButtonType) {
//以枚舉的形似表示---button的界面形式
UIButtonTypeCustom = 0,? ? ? ? ? ? ? ? ? ? ? ? // no button type
UIButtonTypeSystem NS_ENUM_AVAILABLE_IOS(7_0),? // standard system button
UIButtonTypeDetailDisclosure,
UIButtonTypeInfoLight,
UIButtonTypeInfoDark,
UIButtonTypeContactAdd,
UIButtonTypePlain API_AVAILABLE(tvos(11.0)) __IOS_PROHIBITED __WATCHOS_PROHIBITED, // standard system button without the blurred background view
UIButtonTypeRoundedRect = UIButtonTypeSystem? // Deprecated, use UIButtonTypeSystem instead
};
NS_CLASS_AVAILABLE_IOS(2_0) @interface UIButton : UIControl+ (instancetype)buttonWithType:(UIButtonType)buttonType;//創(chuàng)建button
@property(nonatomic)? ? ? ? ? UIEdgeInsets contentEdgeInsets UI_APPEARANCE_SELECTOR; // default is UIEdgeInsetsZero. On tvOS 10 or later, default is nonzero except for custom buttons.調(diào)整button整體內(nèi)部區(qū)域的位置和尺寸
@property(nonatomic)? ? ? ? ? UIEdgeInsets titleEdgeInsets;? ? ? ? ? ? ? ? // default is UIEdgeInsetsZero--調(diào)整button文字區(qū)域的位置和尺寸
@property(nonatomic)? ? ? ? ? BOOL? ? ? ? reversesTitleShadowWhenHighlighted; // default is NO. if YES, shadow reverses to shift between engrave and emboss appearance
@property(nonatomic)? ? ? ? ? UIEdgeInsets imageEdgeInsets;? ? ? ? ? ? ? ? // default is UIEdgeInsetsZero-----調(diào)整button圖片區(qū)域的位置和尺寸
@property(nonatomic)? ? ? ? ? BOOL? ? ? ? adjustsImageWhenHighlighted;? ? // default is YES. if YES, image is drawn darker when highlighted(pressed)
@property(nonatomic)? ? ? ? ? BOOL? ? ? ? adjustsImageWhenDisabled;? ? ? // default is YES. if YES, image is drawn lighter when disabled
@property(nonatomic)? ? ? ? ? BOOL? ? ? ? showsTouchWhenHighlighted __TVOS_PROHIBITED;? ? ? // default is NO. if YES, show a simple feedback (currently a glow) while highlighted
@property(null_resettable, nonatomic,strong)? UIColor? ? *tintColor NS_AVAILABLE_IOS(5_0); // The tintColor is inherited through the superview hierarchy. See UIView for more information.
@property(nonatomic,readonly) UIButtonType buttonType;
// you can set the image, title color, title shadow color, and background image to use for each state. you can specify data
// for a combined state by using the flags added together. in general, you should specify a value for the normal state to be used
// by other states which don't have a custom value set
- (void)setTitle:(nullable NSString *)title forState:(UIControlState)state;? ? ? ? ? ? ? ? ? ? // default is nil. title is assumed to be single line
- (void)setTitleColor:(nullable UIColor *)color forState:(UIControlState)state UI_APPEARANCE_SELECTOR; // default if nil. use opaque white
- (void)setTitleShadowColor:(nullable UIColor *)color forState:(UIControlState)state UI_APPEARANCE_SELECTOR; // default is nil. use 50% black
- (void)setImage:(nullable UIImage *)image forState:(UIControlState)state;? ? ? ? ? ? ? ? ? ? ? // default is nil. should be same size if different for different states
- (void)setBackgroundImage:(nullable UIImage *)image forState:(UIControlState)state UI_APPEARANCE_SELECTOR; // default is nil
- (void)setAttributedTitle:(nullable NSAttributedString *)title forState:(UIControlState)state NS_AVAILABLE_IOS(6_0); // default is nil. title is assumed to be single line
- (nullable NSString *)titleForState:(UIControlState)state;? ? ? ? ? // these getters only take a single state value
- (nullable UIColor *)titleColorForState:(UIControlState)state;
- (nullable UIColor *)titleShadowColorForState:(UIControlState)state;
- (nullable UIImage *)imageForState:(UIControlState)state;
- (nullable UIImage *)backgroundImageForState:(UIControlState)state;
- (nullable NSAttributedString *)attributedTitleForState:(UIControlState)state NS_AVAILABLE_IOS(6_0);
// these are the values that will be used for the current state. you can also use these for overrides. a heuristic will be used to
// determine what image to choose based on the explict states set. For example, the 'normal' state value will be used for all states
// that don't have their own image defined.
@property(nullable, nonatomic,readonly,strong) NSString *currentTitle;? ? ? ? ? ? // normal/highlighted/selected/disabled. can return nil
@property(nonatomic,readonly,strong) UIColor? *currentTitleColor;? ? ? ? // normal/highlighted/selected/disabled. always returns non-nil. default is white(1,1)
@property(nullable, nonatomic,readonly,strong) UIColor? *currentTitleShadowColor;? // normal/highlighted/selected/disabled.
@property(nullable, nonatomic,readonly,strong) UIImage? *currentImage;? ? ? ? ? ? // normal/highlighted/selected/disabled. can return nil
@property(nullable, nonatomic,readonly,strong) UIImage? *currentBackgroundImage;? // normal/highlighted/selected/disabled. can return nil
@property(nullable, nonatomic,readonly,strong) NSAttributedString *currentAttributedTitle NS_AVAILABLE_IOS(6_0);? // normal/highlighted/selected/disabled. can return nil
// return title and image views. will always create them if necessary. always returns nil for system buttons
@property(nullable, nonatomic,readonly,strong) UILabel? ? *titleLabel NS_AVAILABLE_IOS(3_0);
@property(nullable, nonatomic,readonly,strong) UIImageView *imageView? NS_AVAILABLE_IOS(3_0);
/ these return the rectangle for the background (assumes bounds), the content (image + title) and for the image and title separately. the content rect is calculated based
// on the title and image size and padding and then adjusted based on the control content alignment. there are no draw methods since the contents
// are rendered in separate subviews (UIImageView, UILabel)
- (CGRect)backgroundRectForBounds:(CGRect)bounds;
- (CGRect)contentRectForBounds:(CGRect)bounds;// 用來(lái)計(jì)算按鈕整體內(nèi)容區(qū)域的大小和位置
- (CGRect)titleRectForContentRect:(CGRect)contentRect;// 用來(lái)計(jì)算按鈕文字區(qū)域的大小和位置
- (CGRect)imageRectForContentRect:(CGRect)contentRect;// 用來(lái)計(jì)算按鈕圖片區(qū)域的大小和位置
@end
@interface UIButton(UIButtonDeprecated)
@property(nonatomic,strong) UIFont *font NS_DEPRECATED_IOS(2_0, 3_0) __TVOS_PROHIBITED;
@property(nonatomic) NSLineBreakMode lineBreakMode NS_DEPRECATED_IOS(2_0, 3_0) __TVOS_PROHIBITED;
@property(nonatomic) CGSize titleShadowOffset NS_DEPRECATED_IOS(2_0, 3_0) __TVOS_PROHIBITED;
@end#if TARGET_OS_IOS
@interface UIButton (SpringLoading)
@end
#endif
NS_ASSUME_NONNULL_END
注意:默認(rèn)情況下荚孵,Cocoa Touch 框架中的UIButton只支持左圖右文的布局方式坯临,而且還不能直接設(shè)置圖文間距典徘。
但是在現(xiàn)實(shí)開發(fā)中颁督,我們會(huì)遇到要求--上圖片下文字菊霜;右圖左文欲诺;上文下圖的情況狱庇。
針對(duì)這種情況,我們的通常思路就是創(chuàng)建UIButton的子類或者類別
UIButton的類別
#import<UIKit/UIKit.h>
//系統(tǒng)默認(rèn)的布局是內(nèi)容整體居中舀透,圖片在左栓票,文字在右,圖片和文字間距為 0愕够。
typedef NS_ENUM(NSInteger,ZBButtonLayoutStyle) {
ZBButtonLayoutTitleLeft,
ZBButtonLayoutTitleRight,
ZBButtonLayoutTitleTop,
ZBButtonLayoutTitleBottom,
};
@interface UIButton (TitleAndImageLayout)
- (void)zb_setLayoutStyle:(ZBButtonLayoutStyle)style spacing:(CGFloat)spacing;
@end
#import "UIButton+TitleAndImageLayout.h"
@implementation UIButton (TitleAndImageLayout)
- (void)zb_setLayoutStyle:(ZBButtonLayoutStyle)style spacing:(CGFloat)spacing{
[self layoutIfNeeded];//為了獲取最新的 imageView 和 titleLabel 的 frame走贪,強(qiáng)制更新
CGRect titleFrame = self.titleLabel.frame;
CGRect imageFrame = self.imageView.frame;
switch (style) {
//? UIEdgeInsets 類型有四個(gè)成員變量 top、left惑芭、bottom坠狡、right,分別表示上左下右四個(gè)方向的偏移量遂跟,正值代表往內(nèi)縮進(jìn)逃沿,也就是往按鈕中心靠攏,負(fù)值代表往外擴(kuò)張幻锁,就是往按鈕邊緣貼近凯亮。
case ZBButtonLayoutTitleLeft:
{
// 圖片右移
self.imageEdgeInsets = UIEdgeInsetsMake(0,
titleFrame.size.width + spacing,
0,
-(titleFrame.size.width + spacing));
// 文字左移
self.titleEdgeInsets = UIEdgeInsetsMake(0,
-(titleFrame.origin.x - imageFrame.origin.x),
0,
titleFrame.origin.x - imageFrame.origin.x);
}
break;
case ZBButtonLayoutTitleRight:
{
// 計(jì)算默認(rèn)的圖片文字間距
CGFloat originalSpacing = titleFrame.origin.x - (imageFrame.origin.x + imageFrame.size.width);
// 調(diào)整文字的位置
self.titleEdgeInsets = UIEdgeInsetsMake(0,
-(originalSpacing - spacing),
0,
(originalSpacing - spacing));
}
break;
case ZBButtonLayoutTitleTop:
{
// 圖片下移,右移
self.imageEdgeInsets = UIEdgeInsetsMake(titleFrame.size.height + spacing,
0,
0,
-(titleFrame.size.width));
// 文字上移越败,左移
self.titleEdgeInsets = UIEdgeInsetsMake(0,
-(imageFrame.size.width),
imageFrame.size.height + spacing,
0);
}
break;
case ZBButtonLayoutTitleBottom:
{
// 圖片上移触幼,右移
self.imageEdgeInsets = UIEdgeInsetsMake(0,
0,
titleFrame.size.height + spacing,
-(titleFrame.size.width));
// 文字下移,左移
self.titleEdgeInsets = UIEdgeInsetsMake(imageFrame.size.height + spacing,
-(imageFrame.size.width),
0,
0);
}
break;
default:
break;
}
}
@end
使用方法
//button的大小會(huì)自動(dòng)獲取圖片的大小究飞,字體大小默認(rèn)17
UIButton* left = [UIButton buttonWithType:UIButtonTypeCustom];
left.backgroundColor = [UIColor yellowColor];
[self.view addSubview:left];
left.frame = CGRectMake(50, 80, 50, 80);
[left setImage:[UIImage imageNamed:@"icon_交易方式@2x"] forState:UIControlStateNormal];
[left setTitle:@"左" forState:UIControlStateNormal];
left.titleLabel.font = [UIFont systemFontOfSize:36];
[left setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[left zb_setLayoutStyle:ZBButtonLayoutTitleLeft spacing:2];
創(chuàng)建UIButton的子類
#import<UIKit/UIKit.h>
typedef NS_ENUM(NSInteger,ZBButtonLayoutStyle) {
ZBButtonLayoutTitleLeft,
ZBButtonLayoutTitleRight,
ZBButtonLayoutTitleTop,
ZBButtonLayoutTitleBottom,
};
@interface UILayoutButton : UIButton
@property (assign,nonatomic)IBInspectable CGSize imageSize;//圖片大小
@property (nonatomic,assign)CGFloat titleAndImageSpace;//文字和圖片間的距離
@property (assign, nonatomic) ZBButtonLayoutStyle layoutStyle;? ? ///< 圖片和文字的相對(duì)位置
@end
--------------------
#import "UILayoutButton.h"
@implementation UILayoutButton
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
- (void)setLayoutStyle:(ZBButtonLayoutStyle)layoutStyle{
_layoutStyle = layoutStyle;
if (layoutStyle!= ZBButtonLayoutTitleRight&&layoutStyle!= ZBButtonLayoutTitleLeft) {
self.titleLabel.textAlignment = NSTextAlignmentCenter;
}
}
#pragma mark---重寫父類方法置谦,改變title和image的坐標(biāo)
- (CGRect)imageRectForContentRect:(CGRect)contentRect{
if (self.layoutStyle == ZBButtonLayoutTitleLeft) {
CGFloat x = contentRect.size.width - self.titleAndImageSpace - self.imageSize.width ;
CGFloat y =? contentRect.size.height -? self.imageSize.height;
y = y/2;
CGRect rect = CGRectMake(x,y,self.imageSize.width,self.imageSize.height);
return rect;
} else if (self.layoutStyle == ZBButtonLayoutTitleBottom) {
CGFloat x =? contentRect.size.width -? self.imageSize.width;
CGFloat? y=? 0? ;
x = x / 2;
CGRect rect = CGRectMake(x,y,self.imageSize.width,self.imageSize.height);
return rect;
}else if (self.layoutStyle == ZBButtonLayoutTitleTop){
CGFloat x =? contentRect.size.width -? self.imageSize.width;
CGFloat? y=? contentRect.size.height-self.titleAndImageSpace-self.imageSize.height? ;
x = x / 2;
CGRect rect = CGRectMake(x,y,self.imageSize.width,self.imageSize.height);
return rect;
}
else {
return [super imageRectForContentRect:contentRect];
}
}
- (CGRect)titleRectForContentRect:(CGRect)contentRect {
if (self.layoutStyle == ZBButtonLayoutTitleLeft) {
return CGRectMake(0, 0, contentRect.size.width - self.titleAndImageSpace - self.imageSize.width , contentRect.size.height);
} else if (self.layoutStyle == ZBButtonLayoutTitleBottom) {
return CGRectMake(0,? self.titleAndImageSpace + self.imageSize.height , contentRect.size.width , contentRect.size.height - self.titleAndImageSpace - self.imageSize.height );
}
else if (self.layoutStyle == ZBButtonLayoutTitleTop){
return CGRectMake((contentRect.size.width- self.imageSize.width)/2.0 ,? 0 , contentRect.size.width , contentRect.size.height - self.titleAndImageSpace - self.imageSize.height );
}
else {
return [super titleRectForContentRect:contentRect];
}
}
@end
使用方法:
UILayoutButton *left = [UILayoutButton buttonWithType:UIButtonTypeCustom];
left.backgroundColor = [UIColor redColor];
left.titleLabel.backgroundColor = [UIColor grayColor];
left.imageView.backgroundColor = [UIColor purpleColor];
left.frame = CGRectMake(50, 160, 110, 30);
[left setTitle:@"標(biāo)題在左" forState:UIControlStateNormal];
left.imageSize = CGSizeMake(20, 20);//設(shè)置圖片大小
left.layoutStyle = ZBButtonLayoutTitleLeft;//布局風(fēng)格
[left setImage:[UIImage imageNamed:@"check_icon"] forState:UIControlStateNormal];
[self.view addSubview:left];
總結(jié):
以上方式都能實(shí)現(xiàn)重新布局UIButton的子控件的效果,各有優(yōu)缺點(diǎn):
各位堂鲤,可以把您的看法留在下方評(píng)論區(qū)。如有不足媒峡,也請(qǐng)指教瘟栖,我這里就抱磚引玉了。