iOS开发UI之自定义View
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中的子控件托线到关联的类(属性)
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];
}