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.创建UIImageView
        UIImageView *iconImage = [[UIImageView alloc] init];
        self.iconImage = iconImage;
        self.iconImage.image = [UIImage imageNamed:package.icon];
        [self addSubview:iconImage];
        
        // 2.创建UILabel
        UILabel *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中的子控件托线到关联的类(属性)

- (void)init;和- (instancetype)initWithFrame:(NSRect)rect; 这两个初始化方法,即不能通过alloc] init]方法来创建,当加载xib时就会调用- (id)initWithCoder: 方法 ,xib已经加载好后再执行- (void)awakerFromNib

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];
}