1. 通过代码自定义View,创建一个View类(继承UIView),一个View中包含一个UIImageView和一个UILabel
-
外界用alloc] init]方法创建对象时,系统默认会自动调用initWithFrame:(CGRect)frame方法,所以要创建对象View中的子控件需要重写initWithFrame:(CGRect)frame方法,在这个方法中来创建子控件,但不能对其根据创建这个类创建出来的对象尺寸来设置,需要调用
- (void)layoutSubviews 这个方法(当控件尺寸发生改变时就会调用),当在UIControlView.m中创建这个对象,并给它设置尺寸时就会调用这个方法,这时就可以在这个方法中来设置,这个类中的子控件就可以根据对象尺寸来设置自己的尺寸
-
所以一般这这个类中对外提供一个类工厂方法并将
#import "LDPackageView.h"#import "LDPackage.h"@interface LDPackageView ()@property (nonatomic, weak) UIImageView *iconImage;@property (nonatomic, weak) UILabel *nameLabel;@property (nonatomic, strong) LDPackage *package;@end@implementation LDPackageView- (instancetype)initWithPackage:(LDPackage *)package{if (self = [super init]) {_package = package;// 1.创建UIImageViewUIImageView *iconImage = [[UIImageView alloc] init];self.iconImage = iconImage;self.iconImage.image = [UIImage imageNamed:package.icon];[self addSubview:iconImage];// 2.创建UILabelUILabel *nameLabel = [[UILabel alloc] init];self.nameLabel = nameLabel;self.nameLabel.text = package.name;[self addSubview:nameLabel];}return self;}+ (instancetype)packageViewWithPackage:(LDPackage *)package{return [[self alloc] initWithPackage:package];}/*** 当控件尺寸发生改变时就会调用这个方法*/- (void)layoutSubviews
{
[super layouSubviews];// 1.设置iconImage的尺寸和位置CGFloat iconImageW = self.bounds.size.width;CGFloat iconImageH = iconImageW;CGFloat iconImageX = 0;CGFloat iconImageY = 0;self.iconImage.frame = CGRectMake(iconImageX, iconImageY, iconImageW, iconImageH);// 2.设置nameLabel的尺寸和位置CGFloat nameLabelW = iconImageW ;CGFloat nameLabelH = self.bounds.size.height - iconImageH;CGFloat nameLabelX = 0;CGFloat nameLabelY = iconImageH;self.nameLabel.frame = CGRectMake(nameLabelX, nameLabelY, nameLabelW, nameLabelH);self.nameLabel.textAlignment = NSTextAlignmentCenter;self.nameLabel.font = [UIFont systemFontOfSize:13];}@end
2. 通过xib定义View,创建View来管理xib
1> 创建一个xib文件用来描述View中子View布局
2> 创建一个继承与UIView的类,把xib文件和这个类关联
3> 将xib中的子控件托线到关联的类(属性)
4> 外界用这个类创建对象时不会调用- (void)init;和- (instancetype)initWithFrame:(NSRect)rect; 这两个初始化方法,即不能通过alloc] init]方法来创建,当加载xib时就会调用- (id)initWithCoder: 方法 ,xib已经加载好后再执行- (void)awakerFromNib 方法
5> 在创建View对象和View中的子控件时都会调用initWithCoder:
如果xib或者storyboard选中autolayout
如果控件从xib或者storyboard中加载出来,如果该控件还没有显示,是不能通过设置frame来改变控件的尺寸
setFrame : 从xib众加载出来对象就会调用该方法
setImageNames : 主动调用
layoutSubviews : 从xib或者storyboard中加载出来的控件,在控件显示出来之后,才会调用(如果该控件已经显示了,只要改变尺寸就会调用该方法)
使用autolayout和不使用autolayout的却别
使用autolayout : 在调用layoutSubViews方法的时候,会将子控件frame设置成xib中加载出来的frame
不使用autolayout : 在调用layoutSubViews方法的时候,不会将子控件frame设置会xib加载出来的frame
对外提供创建对象的接口如下:
- (instancetype)initWithProduct:(LDProduct *)product{LDProductView *productView = nil;if (self = [super init]) {productView = [[[NSBundle mainBundle] loadNibNamed:@"LDProductView" owner:nil options:nil] firstObject];productView.product = product;productView.imageView.image = [UIImage imageNamed:product.icon];productView.nameLabel.text = product.name;}return productView;}+ (instancetype)productViewWithProduct:(LDProduct *)product{return [[self alloc] initWithProduct:product];}
-
当加载xib的过程中就会执行改方法
- (id)initWithCoder:(NSCoder *)aDecoder{if (self = [super initWithCoder:aDecoder]) {// NSLog(@"initWithCoder");// self.backgroundColor = [UIColor purpleColor];}return self;}
-
当xib已经加载好的时候就会执行该方法
- (void)awakeFromNib{[super awakeFromNib];self.backgroundColor = [UIColor purpleColor];}
3.自定义UIButton类继承UIButton(UIButton内部已经有了UIImageView和UILabel这2个控件)
1> 修改UIButton内部的子控件的frame需要重写父类中两个方法
-
修改子控件UIImageView的frame
- (CGRect)imageRectForContentRect:(CGRect)contentRect{CGFloat width = self.bounds.size.width;CGFloat height = width;return CGRectMake(0, 0, width, height);}
-
修改子控件UILabel的frame
- (CGRect)titleRectForContentRect:(CGRect)contentRect{CGFloat width = self.bounds.size.width;CGFloat height = self.bounds.size.height - width;return CGRectMake(0, width, width, height);}
2> 对外提供一个方法来创建UIButton按钮
// 外界提供一个数据模型,传入后将模型中对象的属性赋值给UIImageView和UILabel- (instancetype)initWithProduct:(LDProduct *)product{if (self = [super init]) {_product = product;[self setImage:[UIImage imageNamed:product.icon] forState:UIControlStateDisabled];[self setTitle:product.name forState:UIControlStateNormal];[self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];self.titleLabel.textAlignment = NSTextAlignmentCenter;self.enabled = NO;}return self;}+ (instancetype)buttonWithProduct:(LDProduct *)product{return [[self alloc] initWithProduct:product];}