iOS中自定义view的封装(iOS中自定义导航栏)
自定义view的封装
如果一个
view
内部的子控件比较多,一般会考虑自定义一个view
,把它内部的子控件创建并封装起来,不让外界看见外界可以传入对应的数据模型给
view
,view
拿到模型数据后,给内部子控件设置对应的数据
代码封装自定义view
代码封装自定义
view
的步骤新建一个继承
UIView
的类在
initWithFrame:
方法中添加子控件(也可以使用懒加载)重写模型属性
set
方法,在set
方法中设置模型属性到子控件上在
layoutSubviews
方法中设置子控件的frame
(一定要调用[super layoutSubviews]
)关于
layoutSubviews
在以下情况下会被调用init
初始化不会触发layoutSubviews
addSubview
会触发layoutSubviews
设置
view
的Frame
会触发layoutSubviews
,当然前提是frame
的值设置前后发生了变化滚动一个
UIScrollView
会触发layoutSubviews
旋转
Screen
会触发父UIView
上的layoutSubviews
事件改变一个
UIView
大小的时候也会触发父UIView
上的layoutSubviews
事件
示例
@class ImageData; @interface ImageDataView : UIView //设置模型属性 @property (nonatomic,strong) ImageData *imageData; @end 复制代码
#import "ImageData.h" @interface ImageDataView() @property (nonatomic,strong) UIImageView *imageView; @property (nonatomic,strong) UILabel *label; @end @implementation ImageDataView - (instancetype)initWithFrame:(CGRect)frame{ if (self = [super initWithFrame:frame]) { } return self; } #pragma mark- 懒加载 - (UIImageView *)imageView{ if (_imageView == nil) { UIImageView *imageView = [[UIImageView alloc]init]; [imageView setBackgroundColor:[UIColor blueColor]]; [self addSubview:imageView]; _imageView = imageView; } return _imageView; } - (UILabel *)label{ if (_label == nil) { UILabel *label = [[UILabel alloc]init]; [label setBackgroundColor:[UIColor redColor]]; label.textAlignment = NSTextAlignmentCenter; [self addSubview:label]; _label = label; } return _label; } #pragma mark- 模型赋值 - (void)setImageData:(ImageData *)imageData{ _imageData = imageData; self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%@",imageData.icon]]; self.label.text = imageData.name; } #pragma mark- 子控件坐标 //这个方法专门用于布局子控件,一般在这里设置子控件的frame //当控件本身的尺寸发送改变时,系统会自动调用这个方法 - (void)layoutSubviews{ [super layoutSubviews]; CGFloat personW = self.frame.size.width; CGFloat personH = self.frame.size.height; self.imageView.frame = CGRectMake(0, 0, personW, personH-20); self.label.frame = CGRectMake(0, personH-20, personW, 20); } @end 复制代码
方法调用
ImageData *imageData = [[ImageData alloc]initWithDic:dic]; ImageDataView *view = [[ImageDataView alloc]init]; view.imageData = imageData; view.frame = CGRectMake(shopX, shopY, imageW, imageH); [bgView addSubview:view]; 复制代码
xib封装自定义view
新建一个继承
UIView
的类新建一个xib文件(xib的文件名最好和控件名一样,修改最外面那个控件的
class
为控件类名 )添加子控件、设置子控件属性
加载 xib 文件
[[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([self class]) owner:self options:nil] lastObject] 复制代码
重写模型属性
set
方法,在set
方法中设置模型属性到子控件上
示例
#import "ImageDataView.h" #import "ImageData.h" @interface ImageDataView() @property (weak, nonatomic) IBOutlet UIImageView *imageView; @property (weak, nonatomic) IBOutlet UILabel *label; @end @implementation ImageDataView + (instancetype)shareImageDataView{ return [[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([self class]) owner:self options:nil] lastObject]; } #pragma mark- 模型赋值 - (void)setImageData:(ImageData *)imageData{ _imageData = imageData; self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%@",imageData.icon]]; self.label.text = imageData.name; } @end 复制代码
两种方法封装自定义view的比较
在调整子控件的
frame
时,使用纯代码比 xib 更灵活,子控件可以在layoutSubviews
方法中灵活调整自己的frame
。而用 xib 相对于比较死板,但是更简单,更方便自定义
view
时,如果该view
一直一个样式,推荐使用xib,简单方便而子控件经常随着父控件变化而变化,推荐使用纯代码,灵活多变
伪原创工具 SEO网站优化 https://www.237it.com/
作者:NewBoy
链接:https://juejin.cn/post/7034859790341931021