採用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的時候,你也可以仿造這個過程去寫。