iOS--MVC、自定义大小可变的view(纯手写)

采用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的时候,你也可以仿造这个过程去写。


















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章