浅谈MVC模式下--动态计算并设置view的frame
来源:互联网 发布:cms内容管理系统 选择 编辑:程序博客网 时间:2024/05/18 16:55
相信大家对MVC这种模式都很熟悉,但是真正理解的并不是很多,也包括我,通俗地说model是数据模型,view是视图模型(一般包含model模型),而controller就是控制model和view的桥梁,有传递数据(传给model)功能,也能控制view(包括大小及位置,展示的样式等等)。
下面就通过一个小小的例子来理解一下MVC怎样使用,并能动态计算view的高度?
首先我们看看整个例子的框架图:
然后我们具体实现的view是这样的
开始动工
Model
两个数据模型:Person和PersonFrame都继承NSObject
FTYPersonModel.h
#import <Foundation/Foundation.h>@interface FTYPersonModel : NSObject/** * 头像名 */@property (copy, nonatomic) NSString *icon;/** * 姓名 */@property (copy, nonatomic) NSString *name;/** * 介绍 */@property (copy, nonatomic) NSString *intro;- (instancetype)initWithDict:(NSDictionary *)dict;+ (instancetype)personModelWithDict:(NSDictionary *)dict;@end
FTYPersonModel.m
#import "FTYPersonModel.h"@implementation FTYPersonModel- (instancetype)initWithDict:(NSDictionary *)dict{ if (self == [super init]) { [self setValuesForKeysWithDictionary:dict]; } return self;}+ (instancetype)personModelWithDict:(NSDictionary *)dict{ return [[FTYPersonModel alloc] initWithDict:dict];}@end
PersonModel模型作用是声明属性
FTYPersonFrameModel.h
#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>@class FTYPersonModel;@interface FTYPersonFrameModel : NSObject/** * person模型 */@property (strong, nonatomic) FTYPersonModel *person;/** * 头像Frame */@property (assign, nonatomic, readonly) CGRect iconFrame;/** * 名称Frame */@property (assign, nonatomic, readonly) CGRect nameFrame;/** * 介绍Frame */@property (assign, nonatomic, readonly) CGRect introFrame;/** * view的高度 */@property (assign, nonatomic, readonly) CGFloat viewHeight;@end
FTYPersonFrameModel包含一个personModel
FTYPersonFrameModel.m
#import "FTYPersonFrameModel.h"#import "FTYPersonModel.h"@implementation FTYPersonFrameModel/** * 重置person * * @param person person */- (void)setPerson:(FTYPersonModel *)person{ _person = person; CGFloat mainWidth = [UIScreen mainScreen].bounds.size.width; CGFloat margin = 10; CGFloat iconWH = 70; _iconFrame = CGRectMake(margin, margin, iconWH, iconWH); CGFloat nameX = CGRectGetMaxX(_iconFrame)+margin; CGFloat maxWidth = mainWidth - margin*2 - iconWH - margin; CGSize size = CGSizeMake(maxWidth, MAXFLOAT); CGSize nameSize = [self sizeCustomWithString:person.name font:[UIFont systemFontOfSize:16.0] constrainedToSize:size]; _nameFrame = CGRectMake(nameX, margin, nameSize.width, nameSize.height); CGFloat introX = nameX; CGFloat introY = CGRectGetMaxY(_nameFrame)+margin; CGSize introSize = [self sizeCustomWithString:person.intro font:[UIFont systemFontOfSize:14.0] constrainedToSize:size]; _introFrame = CGRectMake(introX, introY, introSize.width, introSize.height); if (CGRectGetMaxY(_introFrame) > CGRectGetMaxY(_iconFrame)) { _viewHeight = CGRectGetMaxY(_introFrame) + margin; } else { _viewHeight = CGRectGetMaxY(_iconFrame) + margin; }}/** * 获取最大宽度的字符串size * * @param str 字符串 * @param font 字体大小 * @param constrainedToSize 最大区域 * * @return size */- (CGSize)sizeCustomWithString:(NSString *)str font:(UIFont *)font constrainedToSize:(CGSize)size{ CGSize resultSize; if([self respondsToSelector:@selector(sizeWithAttributes:)]){ NSDictionary *attributes = @{NSFontAttributeName: font}; CGRect rect = [str boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil]; resultSize.width = ceilf(rect.size.width); resultSize.height = ceilf(rect.size.height); }else{#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wdeprecated-declarations" resultSize = [str sizeWithFont:font constrainedToSize:size lineBreakMode:NSLineBreakByWordWrapping];#pragma clang diagnostic pop } return resultSize;}@end
FTYPersonFrameModel的作用就是通过person的值来具体计算出控件所需要的宽度和高度,并赋值给对应的frame;
View
接着我们新建一个视图
FTYPersonView.h
#import <UIKit/UIKit.h>@class FTYPersonFrameModel;@interface FTYPersonView : UIView/** * personFrame模型 */@property (strong, nonatomic) FTYPersonFrameModel *personFrame;@end
FTYPersonView.m
#import "FTYPersonView.h"#import "FTYPersonFrameModel.h"#import "FTYPersonModel.h"@interface FTYPersonView()/** * 头像 */@property (weak, nonatomic) UIImageView *iconView;/** * 名称 */@property (weak, nonatomic) UILabel *nameLabel;/** * 介绍 */@property (weak, nonatomic) UILabel *introLabel;@end@implementation FTYPersonView- (instancetype)initWithFrame:(CGRect)frame{ if (self == [super initWithFrame:frame]) { self.backgroundColor = [UIColor grayColor]; // 初始化控件 UIImageView *imageView = [[UIImageView alloc] init]; _iconView = imageView; [self addSubview:imageView]; UILabel *name = [[UILabel alloc] init]; name.numberOfLines = 0; name.backgroundColor = [UIColor redColor]; name.font = [UIFont systemFontOfSize:16.0]; _nameLabel = name; [self addSubview:name]; UILabel *intro = [[UILabel alloc] init]; intro.numberOfLines = 0; intro.font = [UIFont systemFontOfSize:14.0]; intro.backgroundColor = [UIColor redColor]; _introLabel = intro; [self addSubview:intro]; } return self;}/** * 重置personFrame * * @param personFrame personFrame */- (void)setPersonFrame:(FTYPersonFrameModel *)personFrame{ _personFrame = personFrame; FTYPersonModel *person = personFrame.person; if (person.icon.length > 0 ) { self.iconView.image = [UIImage imageNamed:person.icon]; } else { self.iconView.image = [UIImage imageNamed:@"center_add_friend"]; } self.iconView.frame = personFrame.iconFrame; if (person.name.length > 0) { self.nameLabel.text = person.name; } else { self.nameLabel.text = @"匿名"; } self.nameLabel.frame = personFrame.nameFrame; self.introLabel.text = person.intro; self.introLabel.frame = personFrame.introFrame;}@end
视图view初始化所需要的控件,然后通过一个personFrame属性传值,重置这个属性,获取相对应得值和frame,并设置值和frame。
Controller
FTYPersonViewController.h
#import <UIKit/UIKit.h>@interface FTYPersonViewController : UIViewController@end
FTYPersonViewController.m
#import "FTYPersonViewController.h"#import "FTYPersonFrameModel.h"#import "FTYPersonModel.h"#import "FTYPersonView.h"@interface FTYPersonViewController ()@end@implementation FTYPersonViewController- (void)viewDidLoad { [super viewDidLoad]; FTYPersonModel *person = [[FTYPersonModel alloc] init]; person.icon = nil; person.name = @"圣诞节不发了苏打粉"; person.intro = @"风把类似的反感本拉萨的高发速度跟法师不东风公司的发放第三方把死灵法大陆is发生的部分就爱上当老板发生"; FTYPersonFrameModel *personFrame = [[FTYPersonFrameModel alloc] init]; personFrame.person = person; FTYPersonView *personView = [[FTYPersonView alloc] init]; personView.personFrame = personFrame; personView.frame = CGRectMake(0, 100, self.view.frame.size.width, personFrame.viewHeight); [self.view addSubview:personView];}
FTYPersonViewController初始化数据,并设置view的frame。
效果
包结构
总结:这里可能写的不是很清楚,也非常简单,但是如果你能理解的话,那就进步了不少。其实MVC模式也并不是要理解非常清楚,有时候用多了也就理解了,大家都按照这样的规范写代码,自然而然就形成一种很好的规范,MVC也能很好的理解。
- 浅谈MVC模式下--动态计算并设置view的frame
- Android布局之View.measure()动态量取高度并设置布局--(例:动态计算评论高度并显示)
- Android 动态添加View并设置padding
- VC下动态创建了BUTTON按钮后,如何设置按钮的Modal Frame风格???
- ios 全屏/正常 切换时view.frame 的结构设置
- 设置了view的frame但是还有偏差原因autoresizingMask
- 动态添加未知个View,并动态设置点击事件
- 关于view的frame
- view的frame变化
- UILabel 设置行间距 && 自动计算text 的frame
- 浅谈Spring Mvc的设计模式
- 浅谈对MVC模式的认识
- MVC MVP MVVM模式的浅谈
- 对MVC模式里View的调试
- iOS 动态设置UILabel的frame(宽度和高度)
- 如何自定义一个View,并动态设置style?
- 浅谈MVC模式
- 浅谈MVC设计模式
- Spring实战-雇员薪资管理系统
- Android debug 打印堆栈log
- android常用工具类
- bananapi之system安装
- redis在tag订阅功能中的实践
- 浅谈MVC模式下--动态计算并设置view的frame
- 程序员才看得明白的面试圣经
- Linux内核版本说明
- Gradle 中 buildConfigField的巧妙应用
- java对redis的基本使用(Jedis)
- iOS 访问通讯录
- hibernate和ibatis对比
- Unix Study之--AIX 6.1配置网络安装服务
- MapReduce实现join操作