采用MVC自定义一个view,效果:
思路:
采用MVC,第一步确定model。很明显这个view的model应该由image、string、string组成。model如下:
dataModel:
.h
//
// DataModel.h
// NSOpration
//
// Created by Wu on 16/3/2.
// Copyright © 2016年 Wu. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface DataModel : NSObject
/**
* 数据模型:设备名称、设备状态、下拉角标
*/
@property(nonatomic , strong)NSString *deviceName;
@property(nonatomic , strong)NSString *deviceState;
@property(nonatomic , strong)NSString *icon;
/**
* 利用KVC初始化
*
* @param dict 属性集
*
* @return 数据模型
*/
- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)dataModelWithDict:(NSDictionary *)dict;
@end
.m
//
// DataModel.m
// NSOpration
//
// Created by Wu on 16/3/2.
// Copyright © 2016年 Wu. All rights reserved.
//
#import "DataModel.h"
@implementation DataModel
- (instancetype)initWithDict:(NSDictionary *)dict {
self = [super init];
if (self) {
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
+ (instancetype)dataModelWithDict:(NSDictionary *)dict {
return [[self alloc]initWithDict:dict];
}
@end
说明:一个AV女优就是一部生产AV的设备,所以它们取名icon、deviceName、deviceState。
frameModel:
有了dataModel,必须从dataModel的数据计算出数据的大小来确定label的大小。[说明:这里没有计算view的大小,后面讨论]
.h
//
// FrameModel.h
// NSOpration
//
// Created by Wu on 16/3/2.
// Copyright © 2016年 Wu. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "DataModel.h"
@interface FrameModel : NSObject
/**
* 框架模型:对应数据模型里的属性的frame
*/
@property(nonatomic , assign)CGRect iconFrame;
@property(nonatomic , assign)CGRect deviceNameFrame;
@property(nonatomic , assign)CGRect deviceStatueFrame;
/**
* frame是根据数据的大小计算出来的,所以必须有个数据模型来获取数据
*/
@property(nonatomic , strong)DataModel *dataModel;
+ (instancetype)frameModelWithDataModel:(DataModel *)dataModel;
@end
.m//
// FrameModel.m
// NSOpration
//
// Created by Wu on 16/3/2.
// Copyright © 2016年 Wu. All rights reserved.
//
#import "FrameModel.h"
@implementation FrameModel
- (instancetype)initWithDataModel:(DataModel *)dataModel {
self = [super init];
if (self) {
self.dataModel = dataModel;
}
return self;
}
+ (instancetype)frameModelWithDataModel:(DataModel *)dataModel {
return [[self alloc]initWithDataModel:dataModel];
}
/**
* 重写dataModel的set方法
*
* @param dataModel 数据模型
*/
- (void)setDataModel:(DataModel *)dataModel {
_dataModel = dataModel;
/**
* 设置dataModel后,根据数据计算frame
*/
[self calculateFrame];
}
- (void)calculateFrame {
/**
* 下拉角标
*/
CGFloat iconX = 0;
CGFloat iconY = 0;
CGFloat iconW = 100;
CGFloat iconH = 100;
self.iconFrame = CGRectMake(iconX, iconY, iconW, iconH);
/**
* 设备名称
*/
CGFloat deviceNameX = CGRectGetMaxX(self.iconFrame);
CGFloat deviceNameY = 0;
NSDictionary *nameAttrs = @{NSFontAttributeName : [UIFont systemFontOfSize:25]};
CGSize deviceNameSize = [self.dataModel.deviceName sizeWithAttributes:nameAttrs];
self.deviceNameFrame = (CGRect){{deviceNameX,deviceNameY},{deviceNameSize.width,self.iconFrame.size.height}};
/**
* 设备状态
*/
CGFloat deviceStatueX = 0;
CGFloat deviceStatueY = 100;
CGFloat deviceStatueW = self.iconFrame.size.width + self.deviceNameFrame.size.width;
CGSize deviceStatueSize = CGSizeMake(deviceStatueW, MAXFLOAT);
NSDictionary *statueAttrs = @{NSFontAttributeName : [UIFont systemFontOfSize:17]};
CGFloat deviceStatueH = [self.dataModel.deviceState boundingRectWithSize:deviceStatueSize options:NSStringDrawingUsesLineFragmentOrigin attributes:statueAttrs context:nil].size.height;
NSLog(@"w:%lf|h:%lf",deviceStatueSize.width,deviceStatueSize.height);
self.deviceStatueFrame = (CGRect){{deviceStatueX,deviceStatueY},{deviceStatueW,deviceStatueH}};
// _viewWidth = MAX(deviceNameSize.width, deviceStatueSize.width) + 11;
}
@end
好了,到这里model搭建完毕,现在看view:
.h
//
// DropListView.h
// NSOpration
//
// Created by Wu on 16/3/2.
// Copyright © 2016年 Wu. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "DataModel.h"
#import "FrameModel.h"
//@class DropListView;
//@protocol DropListViewDelegate <NSObject>
//
//@optional
//- (CGFloat)widthOfView:(DropListView *)dropListView;
//
//
//- (void)touch;
//
//@end
@interface DropListView : UIView
//@property(nonatomic , strong)id<DropListViewDelegate> delegate;
@property(nonatomic , strong)DataModel *dataModel;
@property(nonatomic , strong)FrameModel *frameModel;
@end
.m//
// DropListView.m
// NSOpration
//
// Created by Wu on 16/3/2.
// Copyright © 2016年 Wu. All rights reserved.
//
#import "DropListView.h"
@interface DropListView()<UIGestureRecognizerDelegate>
{
UITapGestureRecognizer *_tap;
}
/**
* 显示图片的imageView
*/
@property(nonatomic , strong)UIImageView *iconView;
/**
* 显示设备名称的label
*/
@property(nonatomic , strong)UILabel *deviceLabel;
/**
* 显示设备状态的label
*/
@property(nonatomic , strong)UILabel *statueLabel;
@end
@implementation DropListView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.iconView = [[UIImageView alloc]init];
[self addSubview:self.iconView];
self.deviceLabel = [[UILabel alloc]init];
self.deviceLabel.textAlignment = NSTextAlignmentCenter;
self.deviceLabel.font = [UIFont systemFontOfSize:25];
self.deviceLabel.backgroundColor = [UIColor yellowColor];
[self addSubview:self.deviceLabel];
self.statueLabel = [[UILabel alloc]init];
self.statueLabel.textAlignment = NSTextAlignmentCenter;
self.statueLabel.font = [UIFont systemFontOfSize:17];
self.statueLabel.numberOfLines = 0;
self.statueLabel.backgroundColor = [UIColor grayColor];
[self addSubview:self.statueLabel];
_tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(touch)];
[self.iconView addGestureRecognizer:_tap];
}
return self;
}
- (void)setDataModel:(DataModel *)dataModel {
_dataModel = [[DataModel alloc]init];
_dataModel = dataModel;
self.frameModel = [FrameModel frameModelWithDataModel:dataModel];
self.iconView.image = [UIImage imageNamed:self.dataModel.icon];
self.deviceLabel.text = self.dataModel.deviceName;
self.statueLabel.text = self.dataModel.deviceState;
}
- (void)layoutSubviews {
self.iconView.frame = self.frameModel.iconFrame;
self.deviceLabel.frame = self.frameModel.deviceNameFrame;
self.statueLabel.frame = self.frameModel.deviceStatueFrame;
}
@end
调用://
// ViewController.m
// NSOpration
//
// Created by Wu on 16/3/1.
// Copyright © 2016年 Wu. All rights reserved.
//
#import "ViewController.h"
#import "DropListView.h"
#import "DataModel.h"
#import "FrameModel.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// UILabel *cangLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 300, 100)];
// cangLabel.text = NSLocalizedString(@"myKey", nil);
// [self.view addSubview:cangLabel];
DropListView *view1 = [[DropListView alloc]initWithFrame:CGRectMake(10, 30, 0, 0)];
view1.backgroundColor = [UIColor grayColor];
NSDictionary *dict = @{@"icon":@"li",@"deviceName":@"原纱央莉 | Saori Hara",@"deviceState":@"原纱央莉选择了加入AV界为自己谋求稳定的工作,并且选择了SOD作为自己的东家。在2008年11月25日sabra杂志里当时原纱央莉连载的专栏“SAORIchewBE”里公开了要加入AV的事情。年末,经济普遍不佳时,连带冲击日本写真业。现今AV业者看准这波趋势,在厂商砸钱宣传的效益之下,用一部片接近新台币35万元的价码,说服18名写真女星下海拍A片。其中最成功的例子莫过于德日混血的原纱央莉,因为她竟然拍了3部AV片就狂赚将近7亿新台币,被AV界认为是“奇迹似的写真处女出道”。这也让许多写真女星纷纷脱下比基尼,转换跑道投身AV产业。"};
view1.dataModel = [DataModel dataModelWithDict:dict];
[self.view addSubview:view1];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
完了。
讨论:在frameModel里面我没有计算view的宽度和高度,因为你如果看清楚了这个代码的结构,你会很清楚怎么去做。这个自定义比较粗糙,也没有什么必要。纯手写自定义cell的时候,你也可以仿造这个过程去写。