iOS 第三方框架-Masonry 的视图模块化
来源:互联网 发布:excel2016数据分析在哪 编辑:程序博客网 时间:2024/05/17 00:15
Masonry,是一个基于纯代码的AutoLayout库.初次涉及时,只是感觉它很方便,既有Xib的易读性,又有纯代码的灵活性.试用一段时间之后,突然想到: 或许借助Masonry,建立一个纯代码的不依赖Xib的AutoLayout视图组件机制.
GitHub地址:https://github.com/SnapKit/Masonry
Masonry安装:
source 'https://github.com/CocoaPods/Specs.git'platform :ios, "8.0"use_frameworks!target :testMasonry pod 'Masonry'
目前能得到的效果
- 视图基于 AutoLayout;
- 视图自动适配不同屏幕尺寸;
- 视图完全独立于数据与业务逻辑;
- 视图严肃仅与父视图有位置关系;
- 可以将视图模块的元素与模块同名属性自动关联;
- 仅需知道父视图的宽高,模块内某一个UI元素的宽高, UI元素的 bottom 与 right, 就可以唯一确定任意元素的位置.
核心理论基础: AutoLayout中,如何唯一确定元素在不同尺寸屏幕上的位置?
既定方案,必须基于AutoLayout,至于AutoLayout与Frame的区别于优势,不做赘述.
在不考虑多屏幕兼容的情况下, AutoLayout,可以直接使用固定的约束常量值来确定,但是 马上iPhone 7 都要出来了,指不定什么尺寸呢? 一个机型,一个UI代码?是不是想想都让人头大!
考虑到多屏幕尺寸,UI设计图等比缩放的常用情况,我分享一个可以唯一确定UI元素的方案:
[subView makeConstraints:^(MASConstraintMaker *make) { UIView * superView = subView.superview; make.width.equalTo(superView).multipliedBy(subWidth / superWidth); make.height.equalTo(superView).multipliedBy(subHeight / superHeight); make.right.equalTo(superView).multipliedBy(subRight / superWidth); make.bottom.equalTo(superView).multipliedBy(subBottom / superHeight);}];
以上代码,是整个代码的核心,其巧妙之处在于:不使用constant,而是使用比例来指定约束.选取的是 width,height,right,bottom,而不是其他属性,其巧妙之处,大家试用下其他属性就知道了.
核心代码,打造自己的视图模块库.
直接继承YFViewComponent类,然后实现类方法 subViewsConfig 即可.
//// YFViewComponent.h// testMasonry//// Created by xiao on 16/6/6.// Copyright © 2016年 xiao. All rights reserved.//#import <UIKit/UIKit.h>/** * 预定义常量的声明. *///!< 同一设计图中,视图模块本身的宽度.extern const NSString * YFViewComponentSelfHolderWidthKey;//!< 同一设计图中,视图模块本身的高度.extern const NSString * YFViewComponentSelfHolderHeightKey;//!< 同一设计图中,模块的所有子视图.extern const NSString * YFViewComponentSubViewsKey;//!< 子视图的类型.extern const NSString * YFViewComponentSubViewClassNameKey;//!< 子视图对应的属性,模块中应有属性与其对应,且可通过此属性访问对应的子视图.extern const NSString * YFViewComponentSubViewPropNameKey;//!< 同一设计图中,子视图的宽度.extern const NSString * YFViewComponentSubViewHolderWidthKey;//!< 同一设计图中,子视图的高度.extern const NSString * YFViewComponentSubViewHolderHeightKey;//!< 同一设计图中,子视图的右内边距值(right).extern const NSString * YFViewComponentSubViewHolderRightKey;//!< 同一设计图中,子视图的底部边距值(bottom).extern const NSString * YFViewComponentSubViewHolderBottomKey;@interface YFViewComponent : UIView/** * 子视图配置信息. * * 子类应重写覆盖此方法. * 一个示例: @{ YFViewComponentSelfHolderWidthKey: @640.0, YFViewComponentSelfHolderHeightKey: @155.0, YFViewComponentSubViewsKey: @[@{ YFViewComponentSubViewClassNameKey: NSStringFromClass([UIImageView class]) , YFViewComponentSubViewPropNameKey: @"imageView", YFViewComponentSubViewHolderWidthKey: @160, YFViewComponentSubViewHolderHeightKey: @120, YFViewComponentSubViewHolderBottomKey: @140, YFViewComponentSubViewHolderRightKey: @180 }] } * * @return 返回子视图的配置信息. */+ (NSDictionary *) subViewsConfig;@end
//// YFViewComponent.m// testMasonry//// Created by xiao on 16/6/6.// Copyright © 2016年 xiao. All rights reserved.//#import "YFViewComponent.h"#import "Masonry.h"/** * 预定义常量的定义. */const NSString * YFViewComponentSelfHolderWidthKey = @"YFViewComponentSelfHolderWidthKey";const NSString * YFViewComponentSelfHolderHeightKey = @"YFViewComponentSelfHolderHeightKey";const NSString * YFViewComponentSubViewsKey = @"YFViewComponentSubViewsKey";const NSString * YFViewComponentSubViewClassNameKey = @"YFViewComponentSubViewClassNameKey";const NSString * YFViewComponentSubViewPropNameKey = @"YFViewComponentSubViewPropNameKey";const NSString * YFViewComponentSubViewHolderWidthKey = @"YFViewComponentSubViewHolderWidthKey";const NSString * YFViewComponentSubViewHolderHeightKey = @"YFViewComponentSubViewHolderHeightKey";const NSString * YFViewComponentSubViewHolderRightKey = @"YFViewComponentSubViewHolderRightKey";const NSString * YFViewComponentSubViewHolderBottomKey = @"YFViewComponentSubViewHolderBottomKey";@implementation YFViewComponent- (instancetype)init{ self = [super init]; if (nil != self) { UIView * holderView = self; NSDictionary * config = [[self class] subViewsConfig]; CGFloat superHeight = [[config objectForKey: YFViewComponentSelfHolderHeightKey] floatValue]; CGFloat superWidth = [[config objectForKey: YFViewComponentSelfHolderWidthKey] floatValue];; NSArray * locatArray = [config objectForKey: YFViewComponentSubViewsKey]; [locatArray enumerateObjectsUsingBlock:^(NSDictionary * obj, NSUInteger idx, BOOL *stop) { NSString * classString = [obj objectForKey: YFViewComponentSubViewClassNameKey]; Class viewClass = NSClassFromString(classString); if (YES != [viewClass isSubclassOfClass:[UIView class]]) { return; } UIView * subView = [[viewClass alloc] init]; [holderView addSubview: subView]; NSString * viewKey = [obj objectForKey: YFViewComponentSubViewPropNameKey]; [holderView setValue: subView forKey: viewKey]; CGFloat subWidth = [[obj objectForKey: YFViewComponentSubViewHolderWidthKey] floatValue]; CGFloat subHeight = [[obj objectForKey: YFViewComponentSubViewHolderHeightKey] floatValue]; CGFloat subBottom = [[obj objectForKey: YFViewComponentSubViewHolderBottomKey] floatValue]; CGFloat subRight = [[obj objectForKey: YFViewComponentSubViewHolderRightKey] floatValue]; [subView mas_makeConstraints:^(MASConstraintMaker *make) { UIView * superView = subView.superview; make.width.equalTo(superView).multipliedBy(subWidth / superWidth); make.height.equalTo(superView).multipliedBy(subHeight / superHeight); make.right.equalTo(superView).multipliedBy(subRight / superWidth); make.bottom.equalTo(superView).multipliedBy(subBottom / superHeight); }]; }]; } return self;}+ (NSDictionary *) subViewsConfig{ return nil;}@end
一个示例: 仿网易新闻的新闻单元格.
这个示例,取材自网易新闻.图示中已经标注了单元格的宽高,单元格内各个UI元素的width,height,bottom,right.此处UI设计师可根据屏幕尺寸出图,我们根据一份跟定的设计图,直接使用 MarkMan(一个非常好用的标准工具)丈量标记即可. 因为我们是基于比例来添加约束,不同屏幕下,会自动等比变换.
这是一个简单的示例,为了方便演示,临时加上了:
//// YFAutoTransView.h// testMasonry//// Created by xiao on 16/6/6.// Copyright © 2016年 xiao. All rights reserved.//#import "YFViewComponent.h"@interface YFAutoTransView : YFViewComponent@property (weak, nonatomic) UIImageView * imageView;@property (weak, nonatomic) UILabel * titleLabel;@property (weak, nonatomic) UILabel * detailLabel;@property (weak, nonatomic) UIButton * chatBtn;@end
//// YFAutoTransView.m// testMasonry//// Created by xiao on 16/6/6.// Copyright © 2016年 xiao. All rights reserved.//#import "YFAutoTransView.h"@implementation YFAutoTransView+ (NSDictionary *) subViewsConfig{ NSNumber * holderWidth = @640.0; NSNumber * holderHeight = @155.0; NSArray * subConfig = @[ @[NSStringFromClass([UIImageView class]), @"imageView", @160, @120, @140, @180], @[NSStringFromClass([UILabel class]), @"titleLabel", @420, @31, @55, @615], @[NSStringFromClass([UILabel class]), @"detailLabel", @410, @60, @136, @605], @[NSStringFromClass([UIButton class]), @"chatBtn", @120, @32, @141, @628]]; NSMutableArray * subViewsConfig = [NSMutableArray arrayWithCapacity: 42]; [subConfig enumerateObjectsUsingBlock:^(NSArray * obj, NSUInteger idx, BOOL *stop) { if (6 != obj.count) { return; } NSDictionary * configDict = @{ YFViewComponentSubViewClassNameKey: obj[0], YFViewComponentSubViewPropNameKey: obj[1], YFViewComponentSubViewHolderWidthKey: obj[2], YFViewComponentSubViewHolderHeightKey: obj[3], YFViewComponentSubViewHolderBottomKey: obj[4], YFViewComponentSubViewHolderRightKey: obj[5] }; [subViewsConfig addObject: configDict]; }]; NSDictionary * config = @{ YFViewComponentSelfHolderWidthKey: holderWidth, YFViewComponentSelfHolderHeightKey: holderHeight, YFViewComponentSubViewsKey: subViewsConfig}; return config;}@end
这是与数据结合之后的效果图.只是个初稿,还需要进一步调试.也就是说,以后再写UI界面,你的注意力将可以集中在 数据与视图本身的交互处理上.
//// ViewController.m// testMasonry//// Created by xiao on 16/6/6.// Copyright © 2016年 xiao. All rights reserved.//#import "ViewController.h"#import "YFAutoTransView.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; YFAutoTransView * autoTestView = [[YFAutoTransView alloc] init]; autoTestView.backgroundColor = [UIColor grayColor]; autoTestView.frame = CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 155.0/2); autoTestView.imageView.image = [UIImage imageNamed:@"autoTrans.png"]; autoTestView.imageView.backgroundColor = [UIColor yellowColor]; autoTestView.titleLabel.text = @"爱马仕版苹果表开售8688元起"; autoTestView.titleLabel.font = [UIFont systemFontOfSize:15]; [autoTestView.titleLabel adjustsFontSizeToFitWidth]; autoTestView.detailLabel.text = @"爱马仕版苹果表盘和表带并不会单独销售."; autoTestView.detailLabel.numberOfLines = 0; autoTestView.detailLabel.font = [UIFont systemFontOfSize:12]; [autoTestView.chatBtn setTitle:@"跟帖" forState: UIControlStateNormal]; autoTestView.chatBtn.backgroundColor = [UIColor greenColor]; [self.view addSubview: autoTestView];}@end
运行结果:
- iOS 第三方框架-Masonry 的视图模块化
- iOS 第三方框架-Masonry的使用
- IOS纯代码布局的第三方框架masonry
- iOS 第三方框架-Masonry介绍与使用实践
- 第三方框架Masonry的基本使用
- ios进阶--Autolayout 之第三方框架--Masonry
- ios开发之autolayout 第三方框架Masonry
- 常用第三方框架-Masonry(ios)和SnapKit(swift)
- iOS 第三方库 - Masonry
- Masonry布局第三方框架的使用介绍
- 第三方框架-02.Masonry使用介绍
- iOS---第三方自动布局 - Masonry的使用
- iOS自动布局第三方库Masonry的使用
- iOS 第三方布局工具Masonry
- iOS开发第三方介绍之一Masonry
- iOS开发- Masonry约束第三方详解
- iOS学习之Masonry第三方约束
- iOS常用第三方库之Masonry
- 关于响应式布局
- 透明度百分比与十六进制之间的转换
- 2分钟读懂Hadoop和Spark的异同
- Jquery实现Cookie操作
- pycharm 快捷键
- iOS 第三方框架-Masonry 的视图模块化
- python set
- Android-view事件传递机制
- 电脑问题集合所(待补充)
- STL阅读程序——5
- 人品计算器demo
- Android中adapter的原理简单说明
- Android下拉刷新上拉加载控件,对所有View通用!
- JavaScript学习9张思维导图