1.自定义UIButton更改内部的布局的原因
- 通常我们用系统的UIButton,设置完ImageView跟textLabel的属性之后,图片在左边,文字在右边,有时候我们需要图片在右边,文字在左边就需要自定义了
2.更改内部子控件布局的方式有两种
调整Button内部子控件的步骤 1.自定义Button 2.调整位置 1>重写两个方法:titleRectForContentRect:和imageRectForContentRect: 2>重写layoutSubviews: 先调用super方法.之后自己调整frame 3.如果需要设置imageView和titleLabel的属性时,在initWithFrame:方法设置
// 1.创建UIButton对象 MSHButton *btn = [MSHButton buttonWithType:UIButtonTypeCustom]; 这里是外界的使用,创建 // 2.设置frame btn.frame = CGRectMake(100, 100, 175, 50); // 3.设置背景颜色 [btn setBackgroundColor:[UIColor purpleColor]]; // 4.设置btn显示的文字 [btn setTitle:@"普通按钮" forState:UIControlStateNormal]; // 5.设置btn显示的图片 [btn setImage:[UIImage imageNamed:@"miniplayer_btn_playlist_normal"] forState:UIControlStateNormal]; // 添加到控制器的View中 [self.view addSubview:btn]; // 6.设置btn中titleLabel/imageView的背景颜色 btn.titleLabel.backgroundColor = [UIColor blueColor]; btn.imageView.backgroundColor = [UIColor orangeColor]; // 7.调整titleLabel/imageView的位置 // 注意:不管外界如何调整btn的titleLabel/imageView的位置,button内部都会调整回去 /* btn.titleLabel.frame = CGRectMake(0, 0, 120, 50); btn.imageView.frame = CGRectMake(120, 0, 55, 50); */ /* btn.titleLabel.textAlignment = NSTextAlignmentCenter; btn.imageView.contentMode = UIViewContentModeCenter; */
我们看一下其内部的实现原理
#import "MSHButton.h" @implementation MSHButton - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.titleLabel.textAlignment = NSTextAlignmentCenter; self.imageView.contentMode = UIViewContentModeCenter; } return self; } #pragma mark - 方案一:调整titleLabel和imageView的frame /* // 调整titleLabel的frame - (CGRect)titleRectForContentRect:(CGRect)contentRect { return CGRectMake(0, 0, 120, 50); } // 调整imageView的frame - (CGRect)imageRectForContentRect:(CGRect)contentRect { return CGRectMake(120, 0, 55, 50); } */ #pragma makr - 方案二:重写layoutSubviews - (void)layoutSubviews { [super layoutSubviews]; // 设置子控件的frame self.titleLabel.frame = CGRectMake(0, 0, 120, 50); self.imageView.frame = CGRectMake(120, 0, 55, 50); }
但是前两种都需要设置子控件的frame,下面有一种比较好的方法
@implementation MSHTitleButton // 调整子控件的位置 //- (CGRect)titleRectForContentRect:(CGRect)contentRect //- (CGRect)imageRectForContentRect:(CGRect)contentRect - (void)setTitle:(NSString *)title forState:(UIControlState)state{ [super setTitle:title forState:state]; // 自动计算尺寸 [self sizeToFit]; } - (void)setImage:(UIImage *)image forState:(UIControlState)state{ [super setImage:image forState:state]; // 自动计算尺寸 [self sizeToFit]; } - (void)layoutSubviews{ [super layoutSubviews]; 判断title的x值是不是大于ImageView的X说明,说明是第一次来到该方法中布局,在以后每一次自定义的button尺寸修改之后都会来到该方法,那么以后就直接退出 if (self.imageView.x < self.titleLabel.x) { // NSLog(@"%s",__func__); // 第一次 //调整子控件的位置 // 1.Label 的位置 self.titleLabel.x = self.imageView.x; // 2.调整imageView 的位置 self.imageView.x = CGRectGetMaxX(self.titleLabel.frame); } }