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


















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