前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS-自定义View的封装

iOS-自定义View的封装

作者头像
xy_ss
发布2023-11-22 09:06:09
2850
发布2023-11-22 09:06:09
举报
文章被收录于专栏:浮躁的喧嚣

在开发过程中,自定义控件使用的频率非常高,接下来简单对自定义控件做个小结

View的封装
  • 如果一个view内部的子控件比较多,一般会考虑自定义一个view,把它内部的子控件创建封装起来,不让外界看见
  • 外界可以传入对应的数据模型给view,view拿到模型数据后给内部子控件设置对应的数据
代码封装
  1. 新建一个继承UIView的类
  2. 在initWithFrame:方法中添加子控件(也可以使用懒加载)
  3. 重写模型属性set方法,在set方法中设置模型属性到子控件上
  4. 在layoutSubviews方法中设置子控件的frame(一定要调用[super layoutSubviews])

关于layoutSubviews在以下情况下会被调用:

代码语言:javascript
复制
- init初始化不会触发layoutSubviews
- addSubview会触发layoutSubviews
- 设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化
- 滚动一个UIScrollView会触发layoutSubviews
- 旋转Screen会触发父UIView上的layoutSubviews事件
- 改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件

完整的例子

代码语言:javascript
复制
@class ImageData;
@interface ImageDataView : UIView
//模型
@property (nonatomic,strong) ImageData *imageData;
@end
代码语言:javascript
复制
#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
代码语言:javascript
复制
方法调用
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封装
  1. 新建一个继承UIView的类
  2. 新建一个xib文件(xib的文件名最好和控件名一样,修改最外面那个控件的class为控件类名 )

创建xib

  1. 添加子控件、设置子控件属性

添加子控件

  1. 加载xib文件
代码语言:javascript
复制
[[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([self class]) owner:self options:nil] lastObject]
  1. 重写模型属性set方法,在set方法中设置模型属性到子控件上

完整的例子

代码语言:javascript
复制
#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
两种方法封装UIView的比较
  • 在调整子控件的frame时,使用纯代码比xib更灵活,子控件可以在layoutSubviews方法中灵活调整自己的frame。而用xib相对于比较死板,但是更简单,更方便
  • 自定义UIView时,如果该View一直一个样式,推荐使用xib,简单方便
  • 而子控件经常随着父控件变化而变化,推荐使用纯代码,灵活多变
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-11-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • View的封装
    • 代码封装
      • xib封装
      • 两种方法封装UIView的比较
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档